{"openapi":"3.1.0","info":{"title":"solarOS Organization API","version":"1.0.0","description":"Account-driving API for contractor-owned solarOS data. Use /v1/schema with OpenAPI to discover tenant-specific Lead Field contracts before writing customFields."},"servers":[{"url":"/api/v1"}],"security":[{"OrgApiKey":[]},{"OrgApiKeyHeader":[]}],"components":{"securitySchemes":{"OrgApiKey":{"type":"apiKey","in":"header","name":"Authorization","description":"Organization API key. Format: Bearer sk_live_..."},"OrgApiKeyHeader":{"type":"apiKey","in":"header","name":"x-api-key","description":"Alternative organization API key header for clients that cannot set Authorization."}},"schemas":{"OrgApiMeta":{"type":"object","required":["requestId","version","timestamp"],"properties":{"requestId":{"type":"string"},"version":{"type":"string","const":"v1"},"timestamp":{"type":"string","format":"date-time"},"rateLimit":{"type":"object","properties":{"limit":{"type":"integer"},"remaining":{"type":"integer"},"reset":{"type":"integer"}}}}},"OrgApiError":{"type":"object","required":["error","meta"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}}},"meta":{"$ref":"#/components/schemas/OrgApiMeta"}}},"OrgApiResourceEnvelope":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","additionalProperties":true,"description":"The documented resource shape for the endpoint. Resource-specific fields are described on each operation page and remain additive within v1."},"meta":{"$ref":"#/components/schemas/OrgApiMeta"}}},"OrgApiListEnvelope":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"type":"object","additionalProperties":true}},"meta":{"allOf":[{"$ref":"#/components/schemas/OrgApiMeta"}],"properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}}}}},"OrgApiActionEnvelope":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"object","required":["action"],"properties":{"action":{"type":"object","properties":{"confirmed":{"type":"boolean"},"confirmationSignal":{"type":"string"}}},"resource":{"type":"object","additionalProperties":true}}},"meta":{"$ref":"#/components/schemas/OrgApiMeta"}}},"EffectiveSchema":{"type":"object","required":["schemaVersion","resources","generatedAt"],"properties":{"schemaVersion":{"type":"string"},"generatedAt":{"type":"string","format":"date-time"},"resources":{"type":"object","additionalProperties":{"type":"object","required":["resource","fields"],"properties":{"resource":{"type":"string"},"fields":{"type":"array","items":{"$ref":"#/components/schemas/EffectiveField"}},"customFields":{"type":"array","items":{"$ref":"#/components/schemas/EffectiveCustomField"}},"relationships":{"type":"object","additionalProperties":true},"actions":{"type":"object","additionalProperties":true}}}}}},"EffectiveField":{"type":"object","required":["name","label","answerFormat","required","writable","readOnly"],"properties":{"name":{"type":"string"},"label":{"type":"string"},"answerFormat":{"type":"string"},"required":{"type":"boolean"},"writable":{"type":"boolean"},"readOnly":{"type":"boolean"},"enumOptions":{"type":"array","items":{}},"relationship":{"type":"object","additionalProperties":true},"validation":{"type":"object","additionalProperties":true}}},"EffectiveCustomField":{"allOf":[{"$ref":"#/components/schemas/EffectiveField"},{"type":"object","required":["savedIdentity","fieldId","showIn","isPropertyField"],"properties":{"savedIdentity":{"type":"string"},"fieldId":{"type":"string"},"instructions":{"type":"string"},"fieldArea":{"type":"string","deprecated":true,"description":"Retired Field Area label, frozen at its last stored value and never set on new Fields. Use showIn for where a Field shows."},"showIn":{"$ref":"#/components/schemas/FieldShowIn"},"isPropertyField":{"type":"boolean","description":"True when the Property keeps this Field's answer, so later records at that Property start from it."}}}]},"FieldShowIn":{"type":"object","description":"Where this Field's answer shows. cases is whether every Case lists the Field in its Field Snapshot (a Property Field there shows the property's answer). workOrders, permits, and plansets are the record kinds whose Project Snapshot shows it, as the company chose. applications is worked out from the Application Types that list the Field among the fields their Applications show: { typeIds } naming those types, or NONE. It is never ALL.","required":["cases","workOrders","permits","plansets","applications"],"properties":{"cases":{"type":"boolean"},"workOrders":{"type":"boolean"},"permits":{"type":"boolean"},"plansets":{"type":"boolean"},"applications":{"oneOf":[{"type":"string","enum":["NONE"]},{"type":"object","required":["typeIds"],"properties":{"typeIds":{"type":"array","items":{"type":"string"}}}}]}}},"LeadCreateRequest":{"type":"object","required":["firstName","lastName"],"additionalProperties":false,"properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"address":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zipCode":{"type":"string"},"status":{"type":"string","enum":["NEW","CONTACTED","QUALIFIED","UNQUALIFIED"]},"sourceId":{"type":"string"},"campaignId":{"type":"string"},"salesTypeIds":{"type":"array","items":{"type":"string"}},"ownerId":{"type":"string"},"originatorId":{"type":["string","null"],"description":"The active or draft same-organization Team Member credited with bringing this sale in. When omitted, the owner is credited."},"notes":{"type":"string"},"customFields":{"type":"object","additionalProperties":true,"description":"Field Values keyed by savedIdentity from /v1/schema resources.leads.customFields."},"externalReferences":{"type":"array","items":{"type":"object","required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"}}}}}},"Lead":{"type":"object","required":["id","firstName","lastName","status","customFields"],"properties":{"id":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":["string","null"],"format":"email"},"phone":{"type":["string","null"]},"address":{"type":["string","null"]},"city":{"type":["string","null"]},"state":{"type":["string","null"]},"zipCode":{"type":["string","null"]},"status":{"type":"string"},"sourceId":{"type":["string","null"]},"campaignId":{"type":["string","null"]},"ownerId":{"type":"string"},"originatorId":{"type":"string","description":"The Team Member credited with bringing this sale in."},"originator":{"type":["object","null"],"additionalProperties":true},"notes":{"type":["string","null"]},"source":{"type":["object","null"],"additionalProperties":true},"campaign":{"type":["object","null"],"additionalProperties":true},"owner":{"type":["object","null"],"additionalProperties":true},"salesTypeIds":{"type":"array","items":{"type":"string"}},"salesTypes":{"type":"array","items":{"type":"object"}},"customFields":{"type":"object","additionalProperties":true,"description":"Hydrated placed Field Values keyed by savedIdentity from /v1/schema."},"externalReferences":{"type":"array","items":{"type":"object"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"LeadEnvelope":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Lead"},"meta":{"$ref":"#/components/schemas/OrgApiMeta"}}},"Case":{"type":"object","required":["id","caseNumber","customerId","propertyId","subject","description","origin","severity","category","status","customFields","submissionAnswers","reportedHardware","submittedContact","externalRecordLinks"],"properties":{"id":{"type":"string"},"caseNumber":{"type":"string"},"customerId":{"type":"string"},"propertyId":{"type":"string"},"systemId":{"type":["string","null"]},"projectId":{"type":["string","null"],"deprecated":true,"description":"Current project compatibility pointer; not the membership list."},"currentProjectId":{"type":["string","null"]},"projects":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"projectNumber":{"type":"string"},"name":{"type":"string"},"status":{"type":"string"}}}},"sourceServiceRequestId":{"type":["string","null"]},"subject":{"type":"string"},"description":{"type":"string"},"origin":{"type":"string"},"severity":{"type":"string"},"category":{"type":"string"},"status":{"type":"string"},"resolution":{"type":["string","null"],"description":"The case's Case Resolution key: one of the organization's own list of ways to close a case. Null until the case is closed."},"ownerId":{"type":["string","null"]},"owner":{"type":["object","null"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}},"customer":{"type":"object","properties":{"id":{"type":"string"},"displayName":{"type":"string"}}},"updatedAt":{"type":"string","format":"date-time"},"url":{"type":"string","format":"uri","description":"The Case page in solarOS."},"openedAt":{"type":"string","format":"date-time"},"firstResponseAt":{"type":["string","null"],"format":"date-time","description":"When the organization first reached the customer about the case. A case a team member enters is responded when opened; a case created through the API waits on its first response (null) until it is recorded in solarOS or sent with PATCH."},"resolvedAt":{"type":["string","null"],"format":"date-time"},"closedAt":{"type":["string","null"],"format":"date-time"},"slaResponseDueAt":{"type":["string","null"],"format":"date-time","description":"Respond-by time from the organization's SLA targets for the case's severity. Only cases that arrive on their own (Service Request Form, automatic email, the API) have one."},"slaResolutionDueAt":{"type":["string","null"],"format":"date-time","description":"Resolve-by time from the organization's SLA targets for the case's severity. Moves later by the time the case spends awaiting the customer, a vendor or work."},"externalReferences":{"type":"array","items":{"type":"object","additionalProperties":true}},"customFields":{"type":"object","additionalProperties":true,"description":"Case Field Values keyed by their saved Field identity."},"submissionAnswers":{"type":"object","additionalProperties":true,"description":"One-off Service Request Form answers keyed by entry id, with snapshotted labels."},"reportedHardware":{"type":"array","items":{"type":"object","additionalProperties":true},"description":"Hardware reported by the submitter; this does not change the system of record."},"submittedContact":{"type":["object","null"],"additionalProperties":true,"description":"Contact and property details exactly as submitted."},"externalRecordLinks":{"type":"array","description":"Navigable context links to related records in external systems.","items":{"type":"object","required":["id","externalSystem","externalSystemLabel","objectLabel","recordLabel","url","createdAt"],"properties":{"id":{"type":"string"},"externalSystem":{"type":"string"},"externalSystemLabel":{"type":"string"},"objectLabel":{"type":"string"},"recordLabel":{"type":"string"},"url":{"type":"string","format":"uri"},"externalId":{"type":["string","null"]},"data":{"type":"object","additionalProperties":true},"createdAt":{"type":"string","format":"date-time"}}}}}},"CaseEnvelope":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Case"},"meta":{"$ref":"#/components/schemas/OrgApiMeta"}}},"CaseListEnvelope":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Case"}},"meta":{"$ref":"#/components/schemas/OrgApiMeta"}}},"TeamMemberCreateRequest":{"type":"object","additionalProperties":false,"properties":{"email":{"type":["string","null"],"format":"email"},"firstName":{"type":["string","null"]},"lastName":{"type":["string","null"]},"displayName":{"type":["string","null"]},"phone":{"type":["string","null"]},"role":{"type":"string","enum":["OWNER","ADMIN","SALES_MANAGER","SALES_USER","OPERATIONS_MANAGER","OPERATIONS_USER","TECHNICIAN","MEMBER"],"default":"MEMBER"},"status":{"type":"string","const":"DRAFT","default":"DRAFT"},"schedulable":{"type":"boolean","description":"Whether this Team Member is a Service Resource. Setting true is limited to included scheduling seats; the public API cannot consent to paid seats."},"salesforceUserId":{"type":["string","null"]},"salesforceServiceResourceId":{"type":["string","null"]},"externalReferences":{"type":"array","items":{"type":"object"}}}},"TeamMember":{"type":"object","required":["id","role","isActive","schedulable","status"],"properties":{"id":{"type":"string"},"email":{"type":"string","format":"email"},"firstName":{"type":["string","null"]},"lastName":{"type":["string","null"]},"displayName":{"type":"string"},"role":{"type":"string"},"isActive":{"type":"boolean"},"schedulable":{"type":"boolean","description":"True when this Team Member is a schedulable Service Resource."},"status":{"type":"string","enum":["ACTIVE","DRAFT","INACTIVE"]},"phone":{"type":["string","null"]},"salesforceUserId":{"type":["string","null"]},"salesforceServiceResourceId":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"TeamMemberEnvelope":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/TeamMember"},"meta":{"$ref":"#/components/schemas/OrgApiMeta"}}},"TeamMemberListEnvelope":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TeamMember"}},"meta":{"$ref":"#/components/schemas/OrgApiMeta"}}},"TimeBlock":{"type":"object","required":["id","teamMemberId","teamMember","type","startDate","endDate"],"properties":{"id":{"type":"string"},"teamMemberId":{"type":"string"},"teamMember":{"type":"object","required":["id","displayName"],"properties":{"id":{"type":"string"},"displayName":{"type":"string"},"salesforceServiceResourceId":{"type":["string","null"]}}},"type":{"type":"string","enum":["PTO","SICK","TRAINING","PERSONAL","OTHER"]},"startDate":{"type":"string","format":"date-time"},"endDate":{"type":"string","format":"date-time"},"description":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"TimeBlockEnvelope":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/TimeBlock"},"meta":{"$ref":"#/components/schemas/OrgApiMeta"}}},"TimeBlockListEnvelope":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TimeBlock"}},"meta":{"allOf":[{"$ref":"#/components/schemas/OrgApiMeta"}],"properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}}}}},"MaterialRequest":{"type":"object","required":["id","recordNumber","status","lineItems","url","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"recordNumber":{"type":["string","null"],"description":"Record Number, such as MAT-00200."},"status":{"type":"string","enum":["PENDING","ORDERED","PARTIALLY_RECEIVED","RECEIVED","READY_FOR_PICKUP","PICKED_UP","CANCELLED"]},"neededByDate":{"type":["string","null"],"format":"date-time","description":"neededByDate, orderedDate, expectedDate and receivedDate are days, saved as midnight UTC the way solarOS's date pickers save them."},"vendorName":{"type":["string","null"]},"vendorOrderRef":{"type":["string","null"],"description":"The vendor's order or PO number."},"orderedDate":{"type":["string","null"],"format":"date-time"},"expectedDate":{"type":["string","null"],"format":"date-time"},"receivedDate":{"type":["string","null"],"format":"date-time"},"estimatedCost":{"type":["string","null"],"description":"Decimal string: quantity × unitCost over the line items that are not cancelled."},"actualCost":{"type":["string","null"],"description":"Decimal string."},"notes":{"type":["string","null"]},"pickupLocation":{"type":["object","null"],"required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}},"pickedUpBy":{"type":["object","null"],"description":"The Team Member who picked the materials up. Null when the pickup was recorded through the API.","required":["id","displayName"],"properties":{"id":{"type":"string"},"displayName":{"type":"string"}}},"pickedUpAt":{"type":["string","null"],"format":"date-time"},"workOrder":{"type":["object","null"],"required":["id","number"],"properties":{"id":{"type":"string"},"number":{"type":["string","null"]}}},"project":{"type":["object","null"],"required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"}}},"lineItems":{"type":"array","items":{"type":"object","required":["id","name","quantity","unit","status","receivedQuantity"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"quantity":{"type":"integer"},"unit":{"type":"string"},"unitCost":{"type":["string","null"],"description":"Decimal string."},"product":{"type":["object","null"],"description":"The catalog Product, when the line names one.","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"sku":{"type":["string","null"]}}},"status":{"type":"string","enum":["PENDING","ORDERED","RECEIVED","PICKED_UP","CANCELLED"]},"receivedQuantity":{"type":"integer"}}}},"url":{"type":"string","format":"uri","description":"The Material Request page in solarOS."},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"MaterialRequestEnvelope":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/MaterialRequest"},"meta":{"$ref":"#/components/schemas/OrgApiMeta"}}},"MaterialRequestListEnvelope":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/MaterialRequest"}},"meta":{"allOf":[{"$ref":"#/components/schemas/OrgApiMeta"}],"properties":{"nextCursor":{"type":["string","null"]},"hasMore":{"type":"boolean"}}}}},"PickupLocation":{"type":"object","required":["id","name"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"address":{"type":["string","null"]},"phone":{"type":["string","null"]}}},"PickupLocationListEnvelope":{"type":"object","required":["data","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/PickupLocation"}},"meta":{"$ref":"#/components/schemas/OrgApiMeta"}}},"CampaignCreateRequest":{"type":"object","required":["name"],"additionalProperties":false,"properties":{"name":{"type":"string"},"status":{"type":["string","null"]},"type":{"type":["string","null"]},"description":{"type":["string","null"]},"isActive":{"type":"boolean","default":true},"startDate":{"type":["string","null"],"format":"date"},"endDate":{"type":["string","null"],"format":"date"},"budgetedCost":{"type":["string","number","null"]},"actualCost":{"type":["string","number","null"]},"expectedRevenue":{"type":["string","number","null"]},"expectedResponseRate":{"type":["string","number","null"]},"metadata":{"type":"object","additionalProperties":true},"externalReferences":{"type":"array","items":{"type":"object","required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"Campaign":{"type":"object","required":["id","name","isActive","externalReferences","createdAt","updatedAt"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"status":{"type":["string","null"]},"type":{"type":["string","null"]},"description":{"type":["string","null"]},"isActive":{"type":"boolean"},"startDate":{"type":["string","null"],"format":"date-time"},"endDate":{"type":["string","null"],"format":"date-time"},"budgetedCost":{"type":["string","null"]},"actualCost":{"type":["string","null"]},"expectedRevenue":{"type":["string","null"]},"expectedResponseRate":{"type":["string","null"]},"metadata":{"type":"object","additionalProperties":true},"externalReferences":{"type":"array","items":{"type":"object"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}}},"CampaignEnvelope":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/Campaign"},"meta":{"$ref":"#/components/schemas/OrgApiMeta"}}}}},"paths":{"/communications/calls":{"post":{"operationId":"logCommunicationCall","tags":["Communications"],"summary":"Log a call from a phone system","description":"Requires conversations and phoneSystem enabled. Use E.164 phone numbers (US ten-digit numbers are also accepted). A known customer matches the newest open Case, or their General Conversation when no Case is open. Unknown or ambiguous callers wait in Unmatched for staff selection. A Case hint must belong to the matched customer. Processing is asynchronous; 202 returns id (the Call ID), eventId and status in the data envelope. Repeating an identical request returns the same receipt; reusing a key or provider call ID with different details returns 409. Recording links remain at the provider. Maximum request body: 300,000 bytes.","x-required-scopes":["communications:write"],"x-idempotency-key":"required","responses":{"202":{"description":"Call retained for matching; receipt contains id (the Call ID), eventId and status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: communications:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Idempotency key or provider call ID already used with different details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for logCommunicationCall.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["direction","from","to","startedAt","result"],"properties":{"providerCallId":{"type":"string","maxLength":255,"description":"Stable provider ID, unique within the company. Prefix with the phone system name when using multiple systems. Omit to derive an ID from this API key and Idempotency-Key."},"direction":{"enum":["INBOUND","OUTBOUND"]},"from":{"type":"string"},"to":{"type":"string"},"startedAt":{"type":"string","format":"date-time"},"endedAt":{"type":"string","format":"date-time"},"durationSeconds":{"type":"integer","minimum":0,"maximum":604800,"default":0},"result":{"enum":["ANSWERED","MISSED","VOICEMAIL","BUSY","FAILED"]},"user":{"type":"object","additionalProperties":false,"required":["email"],"properties":{"email":{"type":"string","format":"email","description":"Active company team member who handled the call."}}},"personEmail":{"type":"string","format":"email","description":"Alias of user.email; when both are supplied they must match."},"recordingUrl":{"type":"string","format":"uri","description":"HTTPS provider recording link. Recording audio is never copied into solarOS."},"recordingExpiresAt":{"type":"string","format":"date-time"},"transcript":{"type":"string","maxLength":200000},"summary":{"type":"string","maxLength":20000},"hint":{"type":"object","additionalProperties":false,"properties":{"caseNumber":{"type":["string","integer"]},"customerEmail":{"type":"string","format":"email"}}}}},"examples":{"logcommunicationcallRequest":{"value":{"providerCallId":"phone-system:call-2417","direction":"INBOUND","from":"+17075550101","to":"+17075550102","startedAt":"2026-09-12T17:00:00Z","endedAt":"2026-09-12T17:02:00Z","durationSeconds":120,"result":"ANSWERED","user":{"email":"service@example.com"},"recordingUrl":"https://phone.example.com/recordings/call-2417","transcript":"Customer: The inverter lights are red and green.","summary":"Customer reports red and green inverter lights.","hint":{"caseNumber":"2417"}}}}}}},"x-tool-name":"orgApi.logCommunicationCall","x-llm-guidance":"Log a call from a phone system. Use an organization API key with communications:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/communications/calls\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"providerCallId\":\"phone-system:call-2417\",\"direction\":\"INBOUND\",\"from\":\"+17075550101\",\"to\":\"+17075550102\",\"startedAt\":\"2026-09-12T17:00:00Z\",\"endedAt\":\"2026-09-12T17:02:00Z\",\"durationSeconds\":120,\"result\":\"ANSWERED\",\"user\":{\"email\":\"service@example.com\"},\"recordingUrl\":\"https://phone.example.com/recordings/call-2417\",\"transcript\":\"Customer: The inverter lights are red and green.\",\"summary\":\"Customer reports red and green inverter lights.\",\"hint\":{\"caseNumber\":\"2417\"}}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/communications/calls`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"providerCallId\": \"phone-system:call-2417\",\n    \"direction\": \"INBOUND\",\n    \"from\": \"+17075550101\",\n    \"to\": \"+17075550102\",\n    \"startedAt\": \"2026-09-12T17:00:00Z\",\n    \"endedAt\": \"2026-09-12T17:02:00Z\",\n    \"durationSeconds\": 120,\n    \"result\": \"ANSWERED\",\n    \"user\": {\n      \"email\": \"service@example.com\"\n    },\n    \"recordingUrl\": \"https://phone.example.com/recordings/call-2417\",\n    \"transcript\": \"Customer: The inverter lights are red and green.\",\n    \"summary\": \"Customer reports red and green inverter lights.\",\n    \"hint\": {\n      \"caseNumber\": \"2417\"\n    }\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/communications/calls\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"providerCallId\": \"phone-system:call-2417\",\n  \"direction\": \"INBOUND\",\n  \"from\": \"+17075550101\",\n  \"to\": \"+17075550102\",\n  \"startedAt\": \"2026-09-12T17:00:00Z\",\n  \"endedAt\": \"2026-09-12T17:02:00Z\",\n  \"durationSeconds\": 120,\n  \"result\": \"ANSWERED\",\n  \"user\": {\n    \"email\": \"service@example.com\"\n  },\n  \"recordingUrl\": \"https://phone.example.com/recordings/call-2417\",\n  \"transcript\": \"Customer: The inverter lights are red and green.\",\n  \"summary\": \"Customer reports red and green inverter lights.\",\n  \"hint\": {\n    \"caseNumber\": \"2417\"\n  }\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"log-communication-call","groupSlug":"communications","navigationGroup":"Communications","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/communications/messages":{"post":{"operationId":"logCommunicationMessage","tags":["Communications"],"summary":"Log a text handled by another phone system","description":"Logs an SMS already received or sent by a phone system; this endpoint does not send a text. Requires conversations and phoneSystem enabled. Customer matching and staff review follow the call endpoint. Use E.164 numbers and a timestamp with an explicit offset. Processing is asynchronous; 202 returns id (the Message ID), eventId and status in the data envelope. Repeating an identical request returns the same receipt; reusing a key or provider message ID with different details returns 409. Maximum request body: 100,000 bytes.","x-required-scopes":["communications:write"],"x-idempotency-key":"required","responses":{"202":{"description":"Message retained for matching; receipt contains id (the Message ID), eventId and status","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: communications:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Idempotency key or provider message ID already used with different details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for logCommunicationMessage.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["direction","from","to","occurredAt","content"],"properties":{"providerMessageId":{"type":"string","maxLength":255,"description":"Stable provider ID, unique within the company. Omit to derive an ID from this API key and Idempotency-Key."},"channel":{"const":"SMS","default":"SMS"},"direction":{"enum":["INBOUND","OUTBOUND"]},"from":{"type":"string"},"to":{"type":"string"},"occurredAt":{"type":"string","format":"date-time"},"content":{"type":"string","minLength":1,"maxLength":20000},"status":{"enum":["RECEIVED","SENT","DELIVERED"],"description":"Inbound must be RECEIVED; outbound must be SENT or DELIVERED. Defaults to RECEIVED for inbound and SENT for outbound."},"user":{"type":"object","additionalProperties":false,"required":["email"],"properties":{"email":{"type":"string","format":"email"}}},"hint":{"type":"object","additionalProperties":false,"properties":{"caseNumber":{"type":["string","integer"]},"customerEmail":{"type":"string","format":"email"}}}}},"examples":{"logcommunicationmessageRequest":{"value":{"providerMessageId":"phone-system:message-2417","channel":"SMS","direction":"INBOUND","from":"+17075550101","to":"+17075550102","occurredAt":"2026-09-12T17:03:00Z","content":"I am home after three.","hint":{"caseNumber":"2417"}}}}}}},"x-tool-name":"orgApi.logCommunicationMessage","x-llm-guidance":"Log a text handled by another phone system. Use an organization API key with communications:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/communications/messages\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"providerMessageId\":\"phone-system:message-2417\",\"channel\":\"SMS\",\"direction\":\"INBOUND\",\"from\":\"+17075550101\",\"to\":\"+17075550102\",\"occurredAt\":\"2026-09-12T17:03:00Z\",\"content\":\"I am home after three.\",\"hint\":{\"caseNumber\":\"2417\"}}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/communications/messages`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"providerMessageId\": \"phone-system:message-2417\",\n    \"channel\": \"SMS\",\n    \"direction\": \"INBOUND\",\n    \"from\": \"+17075550101\",\n    \"to\": \"+17075550102\",\n    \"occurredAt\": \"2026-09-12T17:03:00Z\",\n    \"content\": \"I am home after three.\",\n    \"hint\": {\n      \"caseNumber\": \"2417\"\n    }\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/communications/messages\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"providerMessageId\": \"phone-system:message-2417\",\n  \"channel\": \"SMS\",\n  \"direction\": \"INBOUND\",\n  \"from\": \"+17075550101\",\n  \"to\": \"+17075550102\",\n  \"occurredAt\": \"2026-09-12T17:03:00Z\",\n  \"content\": \"I am home after three.\",\n  \"hint\": {\n    \"caseNumber\": \"2417\"\n  }\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"log-communication-message","groupSlug":"communications","navigationGroup":"Communications","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/whoami":{"get":{"operationId":"getApiKeyContext","tags":["Authentication"],"summary":"Inspect the presented organization API key context","description":"Returns the tenant, key prefix/name, granted scopes, rate-limit policy, IP allowlist state, rotation grace state, attribution metadata, and default owners for the API key used on the request. This endpoint requires a valid organization API key but no additional scope.","x-required-scopes":[],"x-tool-name":"orgApi.getApiKeyContext","x-llm-guidance":"Call this first when debugging credentials or confirming which organization, scopes, and defaults an agent is using. Never ask the user to paste an existing plaintext key into a browser client.","responses":{"200":{"description":"API key context envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/whoami\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/whoami`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/whoami\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-api-key-context","groupSlug":"auth","navigationGroup":"Auth","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/schema":{"get":{"operationId":"getEffectiveSchema","tags":["Schema"],"summary":"Get tenant-specific effective schema","description":"Returns the calling organization effective Lead contract, including standard fields, placed Fields, writable/read-only state, requiredness, enum options, validation, relationship constraints, schema version, and generation timestamp. Required scope: schema:read.","x-required-scopes":["schema:read"],"responses":{"200":{"description":"Effective schema envelope","content":{"application/json":{"schema":{"type":"object","required":["data","meta"],"properties":{"data":{"$ref":"#/components/schemas/EffectiveSchema"},"meta":{"$ref":"#/components/schemas/OrgApiMeta"}}}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing schema:read scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.getEffectiveSchema","x-llm-guidance":"Get tenant-specific effective schema. Use an organization API key with schema:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/schema\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/schema`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/schema\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-effective-schema","groupSlug":"schema","navigationGroup":"Schema","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/lead-sources":{"get":{"operationId":"listLeadSources","tags":["Lead Sources"],"summary":"List active Lead Sources","description":"Returns active Lead Source catalog entries for the authenticated organization only. Use these ids as sourceId when creating or updating Leads. Required scope: lead_sources:read.","x-required-scopes":["lead_sources:read"],"responses":{"200":{"description":"Lead Source list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing lead_sources:read scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.listLeadSources","x-llm-guidance":"List active Lead Sources. Use an organization API key with lead_sources:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/lead-sources\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/lead-sources`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/lead-sources\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-lead-sources","groupSlug":"leads","navigationGroup":"Leads","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/sales-types":{"get":{"operationId":"listSalesTypes","tags":["Sales Types"],"summary":"List active Sales Types","description":"Returns active Sales Type catalog entries for the authenticated organization only. Use these ids in salesTypeIds when creating Leads. Required scope: sales_types:read.","x-required-scopes":["sales_types:read"],"responses":{"200":{"description":"Sales Type list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing sales_types:read scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.listSalesTypes","x-llm-guidance":"List active Sales Types. Use an organization API key with sales_types:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/sales-types\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/sales-types`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/sales-types\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-sales-types","groupSlug":"sales-types","navigationGroup":"Sales Types","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/external-references/lookup":{"get":{"operationId":"lookupExternalReference","tags":["External References"],"summary":"Lookup a solarOS resource by External Reference","description":"Resolves one tenant-owned External Reference tuple to the matching solarOS resourceType and resourceId. Missing or cross-tenant matches return 404. Required scope: external_references:read.","x-required-scopes":["external_references:read"],"parameters":[{"name":"externalSystem","in":"query","required":true,"description":"External Reference system filter. Supply with externalObject and externalId for exact reconciliation lookup.","schema":{"type":"string"}},{"name":"externalObject","in":"query","required":true,"description":"External Reference object filter. Supply with externalSystem and externalId.","schema":{"type":"string"}},{"name":"externalId","in":"query","required":true,"description":"External Reference id filter. Supply with externalSystem and externalObject.","schema":{"type":"string"}}],"responses":{"200":{"description":"External Reference lookup envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Missing or invalid lookup tuple","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: external_references:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"External Reference not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.lookupExternalReference","x-llm-guidance":"Lookup a solarOS resource by External Reference. Use an organization API key with external_references:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/external-references/lookup\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/external-references/lookup`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/external-references/lookup\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"lookup-external-reference","groupSlug":"external-references","navigationGroup":"External References","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/external-references/lookup/batch":{"post":{"operationId":"lookupExternalReferencesBatch","tags":["External References"],"summary":"Lookup External References in a batch","description":"Resolves 1 to 200 tenant-owned External Reference tuples in request order. A missing tuple returns null resourceType, resourceId, and externalReference values in its result instead of failing the whole batch. Duplicate inputs are queried once but remain duplicated in the ordered response. Required scope: external_references:read.","x-required-scopes":["external_references:read"],"responses":{"200":{"description":"Ordered External Reference lookup results envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Invalid or oversized lookup batch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing external_references:read scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for lookupExternalReferencesBatch.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["lookups"],"properties":{"lookups":{"type":"array","minItems":1,"maxItems":200,"items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"}}}}}},"examples":{"lookupexternalreferencesbatchRequest":{"value":{"lookups":[{"externalSystem":"salesforce","externalObject":"WorkOrder","externalId":"0WO123"}]}}}}}},"x-tool-name":"orgApi.lookupExternalReferencesBatch","x-llm-guidance":"Lookup External References in a batch. Use an organization API key with external_references:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/external-references/lookup/batch\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"lookups\":[{\"externalSystem\":\"salesforce\",\"externalObject\":\"WorkOrder\",\"externalId\":\"0WO123\"}]}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/external-references/lookup/batch`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"lookups\": [\n      {\n        \"externalSystem\": \"salesforce\",\n        \"externalObject\": \"WorkOrder\",\n        \"externalId\": \"0WO123\"\n      }\n    ]\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/external-references/lookup/batch\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"lookups\": [\n    {\n      \"externalSystem\": \"salesforce\",\n      \"externalObject\": \"WorkOrder\",\n      \"externalId\": \"0WO123\"\n    }\n  ]\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"lookup-external-references-batch","groupSlug":"external-references","navigationGroup":"External References","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/external-references":{"post":{"operationId":"createExternalReference","tags":["External References"],"summary":"Create an External Reference","description":"Creates or replays one tenant-scoped External Reference for a solarOS resource. Replays return the existing reference when the tuple already points at the same resource; conflicts return 409. Required scope: external_references:write.","x-required-scopes":["external_references:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["resourceType","resourceId","externalSystem","externalObject","externalId"],"properties":{"resourceType":{"type":"string"},"resourceId":{"type":"string"},"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}},"examples":{"createexternalreferenceRequest":{"value":{"resourceType":"WorkOrder","resourceId":"work_order_123","externalSystem":"salesforce","externalObject":"WorkOrder","externalId":"0WO123"}}}}},"description":"JSON request payload for createExternalReference."},"responses":{"200":{"description":"Existing matching External Reference envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"201":{"description":"External Reference created envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Invalid External Reference payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing external_references:write scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"External Reference tuple already points elsewhere","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.createExternalReference","x-llm-guidance":"Create an External Reference. Use an organization API key with external_references:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/external-references\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"resourceType\":\"WorkOrder\",\"resourceId\":\"work_order_123\",\"externalSystem\":\"salesforce\",\"externalObject\":\"WorkOrder\",\"externalId\":\"0WO123\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/external-references`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"resourceType\": \"WorkOrder\",\n    \"resourceId\": \"work_order_123\",\n    \"externalSystem\": \"salesforce\",\n    \"externalObject\": \"WorkOrder\",\n    \"externalId\": \"0WO123\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/external-references\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"resourceType\": \"WorkOrder\",\n  \"resourceId\": \"work_order_123\",\n  \"externalSystem\": \"salesforce\",\n  \"externalObject\": \"WorkOrder\",\n  \"externalId\": \"0WO123\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-external-reference","groupSlug":"external-references","navigationGroup":"External References","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"patch":{"operationId":"repairExternalReference","tags":["External References"],"summary":"Repair an External Reference target","description":"Repoints one existing tenant-scoped External Reference only when expectedCurrentResourceType and expectedCurrentResourceId exactly match the current target. Missing tuples return 404; stale guards return 409. Required scope: external_references:write.","x-required-scopes":["external_references:write"],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["resourceType","resourceId","expectedCurrentResourceType","expectedCurrentResourceId","externalSystem","externalObject","externalId"],"properties":{"resourceType":{"type":"string"},"resourceId":{"type":"string"},"expectedCurrentResourceType":{"type":"string"},"expectedCurrentResourceId":{"type":"string"},"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}},"examples":{"repairexternalreferenceRequest":{"value":{"resourceType":"WorkOrder","resourceId":"work_order_456","expectedCurrentResourceType":"WorkOrder","expectedCurrentResourceId":"work_order_123","externalSystem":"salesforce","externalObject":"WorkOrder","externalId":"0WO123"}}}}},"description":"JSON request payload for repairExternalReference."},"responses":{"200":{"description":"External Reference repaired envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Invalid External Reference repair payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing external_references:write scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"External Reference not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Expected current target did not match","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.repairExternalReference","x-llm-guidance":"Repair an External Reference target. Use an organization API key with external_references:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/external-references\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"resourceType\":\"WorkOrder\",\"resourceId\":\"work_order_456\",\"expectedCurrentResourceType\":\"WorkOrder\",\"expectedCurrentResourceId\":\"work_order_123\",\"externalSystem\":\"salesforce\",\"externalObject\":\"WorkOrder\",\"externalId\":\"0WO123\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/external-references`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"resourceType\": \"WorkOrder\",\n    \"resourceId\": \"work_order_456\",\n    \"expectedCurrentResourceType\": \"WorkOrder\",\n    \"expectedCurrentResourceId\": \"work_order_123\",\n    \"externalSystem\": \"salesforce\",\n    \"externalObject\": \"WorkOrder\",\n    \"externalId\": \"0WO123\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/external-references\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"resourceType\": \"WorkOrder\",\n  \"resourceId\": \"work_order_456\",\n  \"expectedCurrentResourceType\": \"WorkOrder\",\n  \"expectedCurrentResourceId\": \"work_order_123\",\n  \"externalSystem\": \"salesforce\",\n  \"externalObject\": \"WorkOrder\",\n  \"externalId\": \"0WO123\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"repair-external-reference","groupSlug":"external-references","navigationGroup":"External References","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"delete":{"operationId":"deleteExternalReference","tags":["External References"],"summary":"Delete an External Reference","description":"Deletes one tenant-scoped External Reference tuple. The operation is idempotent when the tuple is already absent. Supply expectedResourceType and expectedResourceId to guard against deleting a tuple that was repointed by another worker. Unlike most DELETE endpoints, this operation requires a JSON request body. Required scope: external_references:write.","x-required-scopes":["external_references:write"],"responses":{"200":{"description":"Delete result envelope with deleted and id fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"400":{"description":"Invalid External Reference delete payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing external_references:write scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Expected current target did not match","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for deleteExternalReference.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"expectedResourceType":{"type":"string"},"expectedResourceId":{"type":"string"}}},"examples":{"deleteexternalreferenceRequest":{"value":{"externalSystem":"salesforce","externalObject":"WorkOrder","externalId":"0WO123","expectedResourceType":"WorkOrder","expectedResourceId":"work_order_123"}}}}}},"x-tool-name":"orgApi.deleteExternalReference","x-llm-guidance":"Delete an External Reference. Use an organization API key with external_references:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X DELETE \"$SOLAROS_BASE_URL/api/v1/external-references\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"externalSystem\":\"salesforce\",\"externalObject\":\"WorkOrder\",\"externalId\":\"0WO123\",\"expectedResourceType\":\"WorkOrder\",\"expectedResourceId\":\"work_order_123\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/external-references`, {\n  method: 'DELETE',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"externalSystem\": \"salesforce\",\n    \"externalObject\": \"WorkOrder\",\n    \"externalId\": \"0WO123\",\n    \"expectedResourceType\": \"WorkOrder\",\n    \"expectedResourceId\": \"work_order_123\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"DELETE\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/external-references\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"externalSystem\": \"salesforce\",\n  \"externalObject\": \"WorkOrder\",\n  \"externalId\": \"0WO123\",\n  \"expectedResourceType\": \"WorkOrder\",\n  \"expectedResourceId\": \"work_order_123\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"delete-external-reference","groupSlug":"external-references","navigationGroup":"External References","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/campaigns":{"get":{"operationId":"listCampaigns","tags":["Campaigns"],"summary":"List Campaigns","description":"Lists tenant-scoped Campaign records with cursor pagination, status/type/isActive filters, sorting, and External References. Supply externalSystem, externalObject, and externalId together to filter by a canonical External Reference. Required scope: campaigns:read.","x-required-scopes":["campaigns:read"],"parameters":[{"name":"limit","in":"query","description":"Maximum number of Campaigns to return. Values above 100 are capped at 100.","schema":{"type":"integer","maximum":100}},{"name":"cursor","in":"query","description":"Opaque pagination cursor from the previous response meta.nextCursor value.","schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter Campaigns by integration-defined status.","schema":{"type":"string"}},{"name":"type","in":"query","description":"Filter Campaigns by integration-defined campaign type.","schema":{"type":"string"}},{"name":"isActive","in":"query","description":"Filter active or inactive Campaigns.","schema":{"type":"string","enum":["true","false"]}},{"name":"sortDir","in":"query","description":"Sort direction for createdAt/id ordering.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"externalSystem","in":"query","required":false,"description":"External Reference system filter. Supply with externalObject and externalId for exact reconciliation lookup.","schema":{"type":"string"}},{"name":"externalObject","in":"query","required":false,"description":"External Reference object filter. Supply with externalSystem and externalId.","schema":{"type":"string"}},{"name":"externalId","in":"query","required":false,"description":"External Reference id filter. Supply with externalSystem and externalObject.","schema":{"type":"string"}}],"responses":{"200":{"description":"Campaign list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"400":{"description":"Unsupported filter or sort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing campaigns:read scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.listCampaigns","x-llm-guidance":"List Campaigns. Use an organization API key with campaigns:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/campaigns\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/campaigns`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/campaigns\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-campaigns","groupSlug":"campaigns","navigationGroup":"Campaigns","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"post":{"operationId":"createCampaign","tags":["Campaigns"],"summary":"Create a Campaign","description":"Creates one tenant-scoped Campaign. Requires Idempotency-Key. External References are created transactionally and conflicts return 409. Writes emit campaign.created for webhook subscribers. Required scope: campaigns:write.","x-required-scopes":["campaigns:write"],"x-idempotency-key":"required","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"status":{"type":["string","null"]},"type":{"type":["string","null"]},"description":{"type":["string","null"]},"isActive":{"type":"boolean"},"startDate":{"type":["string","null"],"format":"date"},"endDate":{"type":["string","null"],"format":"date"},"budgetedCost":{"type":["string","number","null"]},"actualCost":{"type":["string","number","null"]},"expectedRevenue":{"type":["string","number","null"]},"expectedResponseRate":{"type":["string","number","null"]},"metadata":{"type":"object","additionalProperties":true},"externalReferences":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"examples":{"createcampaignRequest":{"value":{"name":"Fall referral campaign","status":"active","type":"referral","isActive":true}}}}},"description":"JSON request payload for createCampaign."},"responses":{"201":{"description":"Created Campaign envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignEnvelope"}}}},"400":{"description":"Validation or idempotency error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: campaigns:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Idempotency or External Reference conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.createCampaign","x-llm-guidance":"Create a Campaign. Use an organization API key with campaigns:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/campaigns\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"name\":\"Fall referral campaign\",\"status\":\"active\",\"type\":\"referral\",\"isActive\":true}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/campaigns`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"name\": \"Fall referral campaign\",\n    \"status\": \"active\",\n    \"type\": \"referral\",\n    \"isActive\": true\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/campaigns\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"name\": \"Fall referral campaign\",\n  \"status\": \"active\",\n  \"type\": \"referral\",\n  \"isActive\": true\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-campaign","groupSlug":"campaigns","navigationGroup":"Campaigns","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/campaigns/{id}":{"get":{"operationId":"getCampaign","tags":["Campaigns"],"summary":"Get one Campaign","description":"Returns one Campaign by solarOS id inside the authenticated organization boundary with External References. Required scope: campaigns:read.","x-required-scopes":["campaigns:read"],"responses":{"200":{"description":"Campaign detail envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CampaignEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: campaigns:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Campaign not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Campaign identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getCampaign","x-llm-guidance":"Get one Campaign. Use an organization API key with campaigns:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/campaigns/$SOLAROS_CAMPAIGN\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/campaigns/${process.env.SOLAROS_CAMPAIGN}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/campaigns/{os.environ['SOLAROS_CAMPAIGN']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-campaign","groupSlug":"campaigns","navigationGroup":"Campaigns","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"patch":{"operationId":"updateCampaign","tags":["Campaigns"],"summary":"Update one Campaign","description":"Updates standard Campaign fields and may append External References. No-op PATCH returns changed=false without audit or domain events. Material updates emit campaign.updated. Required scope: campaigns:write.","x-required-scopes":["campaigns:write"],"responses":{"200":{"description":"Updated Campaign envelope with changed metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: campaigns:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Campaign not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"External Reference conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Campaign identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for updateCampaign.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"status":{"type":["string","null"]},"type":{"type":["string","null"]},"description":{"type":["string","null"]},"isActive":{"type":"boolean"},"startDate":{"type":["string","null"],"format":"date"},"endDate":{"type":["string","null"],"format":"date"},"budgetedCost":{"type":["string","number","null"]},"actualCost":{"type":["string","number","null"]},"expectedRevenue":{"type":["string","number","null"]},"expectedResponseRate":{"type":["string","number","null"]},"metadata":{"type":"object","additionalProperties":true},"externalReferences":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"examples":{"updatecampaignRequest":{"value":{"status":"completed","isActive":false}}}}}},"x-tool-name":"orgApi.updateCampaign","x-llm-guidance":"Update one Campaign. Use an organization API key with campaigns:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/campaigns/$SOLAROS_CAMPAIGN\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"status\":\"completed\",\"isActive\":false}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/campaigns/${process.env.SOLAROS_CAMPAIGN}`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"status\": \"completed\",\n    \"isActive\": false\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/campaigns/{os.environ['SOLAROS_CAMPAIGN']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"status\": \"completed\",\n  \"isActive\": false\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"update-campaign","groupSlug":"campaigns","navigationGroup":"Campaigns","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/manifests/schema":{"get":{"operationId":"getTemplateManifestSchema","tags":["Project Template Manifests"],"summary":"Get the Project Template manifest JSON Schema","description":"Returns the JSON Schema contract for project template manifests. This legacy manifest endpoint requires a valid organization API key and is retained for template automation clients.","x-required-scopes":[],"responses":{"200":{"description":"Template manifest schema","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.getTemplateManifestSchema","x-llm-guidance":"Get the Project Template manifest JSON Schema. Use any valid organization API key. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/manifests/schema\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/manifests/schema`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/manifests/schema\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-template-manifest-schema","groupSlug":"project-template-manifests","navigationGroup":"Project Template Manifests","sampleCoverage":"static-complete","coverageDepth":"coverage-status","examplesMode":"static"}}},"/manifests/item-types":{"get":{"operationId":"listTemplateManifestItemTypes","tags":["Project Template Manifests"],"summary":"List supported Project Template manifest item types","description":"Returns static metadata for item types accepted by Project Template manifests.","x-required-scopes":[],"responses":{"200":{"description":"Manifest item type catalog","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.listTemplateManifestItemTypes","x-llm-guidance":"List supported Project Template manifest item types. Use any valid organization API key. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/manifests/item-types\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/manifests/item-types`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/manifests/item-types\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-template-manifest-item-types","groupSlug":"project-template-manifests","navigationGroup":"Project Template Manifests","sampleCoverage":"static-complete","coverageDepth":"coverage-status","examplesMode":"static"}}},"/manifests/report-types":{"get":{"operationId":"listTemplateManifestReportTypes","tags":["Project Template Manifests"],"summary":"List Report Types available to Project Template manifests","description":"Returns platform and organization Report Types that manifest REPORT items can reference.","x-required-scopes":[],"responses":{"200":{"description":"Report Type catalog","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.listTemplateManifestReportTypes","x-llm-guidance":"List Report Types available to Project Template manifests. Use any valid organization API key. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/manifests/report-types\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/manifests/report-types`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/manifests/report-types\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-template-manifest-report-types","groupSlug":"project-template-manifests","navigationGroup":"Project Template Manifests","sampleCoverage":"static-complete","coverageDepth":"coverage-status","examplesMode":"static"}}},"/manifests/templates":{"get":{"operationId":"listTemplateManifests","tags":["Project Template Manifests"],"summary":"List Project Templates available as manifests","description":"Lists organization Project Templates. isActive is the Enabled/Disabled state; publishedOnly is a deprecated enabled-only alias. Filter by versionGroupId; legacy type filtering returns 400.","x-required-scopes":[],"responses":{"200":{"description":"Template manifest list","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.listTemplateManifests","x-llm-guidance":"List Project Templates available as manifests. Use any valid organization API key. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/manifests/templates\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/manifests/templates`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/manifests/templates\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-template-manifests","groupSlug":"project-template-manifests","navigationGroup":"Project Template Manifests","sampleCoverage":"static-complete","coverageDepth":"coverage-status","examplesMode":"static"}},"post":{"operationId":"createTemplateFromManifest","tags":["Project Template Manifests"],"summary":"Create a Project Template from a manifest","description":"Creates an independent Disabled Project Template at version 1. Legacy manifest.type is ignored. options.isPublished=true or options.isActive=true returns 400; enable explicitly using PATCH after reviewing the saved definition. Manifests may carry paymentEventMarks (event key + step name); unknown event keys return 400.","x-required-scopes":[],"responses":{"201":{"description":"Created Project Template manifest result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Invalid JSON or manifest validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Duplicate active template name","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for createTemplateFromManifest.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"name":{"type":"string"},"stages":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"name":{"type":"string"},"items":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"type":{"type":"string"},"title":{"type":"string"}}}}}}}}},"examples":{"createtemplatefrommanifestRequest":{"value":{"name":"Residential PV install","stages":[{"name":"Install","items":[{"type":"WORK_ORDER","title":"Install array"}]}]}}}}}},"x-tool-name":"orgApi.createTemplateFromManifest","x-llm-guidance":"Create a Project Template from a manifest. Use any valid organization API key. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/manifests/templates\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"name\":\"Residential PV install\",\"stages\":[{\"name\":\"Install\",\"items\":[{\"type\":\"WORK_ORDER\",\"title\":\"Install array\"}]}]}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/manifests/templates`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"name\": \"Residential PV install\",\n    \"stages\": [\n      {\n        \"name\": \"Install\",\n        \"items\": [\n          {\n            \"type\": \"WORK_ORDER\",\n            \"title\": \"Install array\"\n          }\n        ]\n      }\n    ]\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/manifests/templates\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"name\": \"Residential PV install\",\n  \"stages\": [\n    {\n      \"name\": \"Install\",\n      \"items\": [\n        {\n          \"type\": \"WORK_ORDER\",\n          \"title\": \"Install array\"\n        }\n      ]\n    }\n  ]\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-template-from-manifest","groupSlug":"project-template-manifests","navigationGroup":"Project Template Manifests","sampleCoverage":"static-complete","coverageDepth":"coverage-status","examplesMode":"static"}}},"/manifests/templates/{id}":{"patch":{"operationId":"setTemplateManifestAvailability","tags":["Project Template Manifests"],"summary":"Enable or disable a saved company Project Template","description":"Set isActive. Enabling validates the saved definition. isPublished is a deprecated alias and must agree if both flags are present. Only the selected template changes; revisions and committed work are preserved.","x-required-scopes":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"isActive":{"type":"boolean"},"isPublished":{"type":"boolean","deprecated":true}},"additionalProperties":false,"anyOf":[{"required":["isActive"]},{"required":["isPublished"]}]},"example":{"isActive":true},"examples":{"settemplatemanifestavailabilityRequest":{"value":{"note":"Request payload for project-template-manifests.","externalReferences":[{"externalSystem":"crm","externalObject":"Project Template Manifests","externalId":"project-template-manifests_external_123"}]}}}}},"description":"JSON request payload for setTemplateManifestAvailability."},"responses":{"200":{"description":"Template availability","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Invalid flags or workflow configuration","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Company template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Template identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.setTemplateManifestAvailability","x-llm-guidance":"Enable or disable a saved company Project Template. Use any valid organization API key. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/manifests/templates/$SOLAROS_TEMPLATE\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"note\":\"Request payload for project-template-manifests.\",\"externalReferences\":[{\"externalSystem\":\"crm\",\"externalObject\":\"Project Template Manifests\",\"externalId\":\"project-template-manifests_external_123\"}]}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/manifests/templates/${process.env.SOLAROS_TEMPLATE}`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"note\": \"Request payload for project-template-manifests.\",\n    \"externalReferences\": [\n      {\n        \"externalSystem\": \"crm\",\n        \"externalObject\": \"Project Template Manifests\",\n        \"externalId\": \"project-template-manifests_external_123\"\n      }\n    ]\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/manifests/templates/{os.environ['SOLAROS_TEMPLATE']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"note\": \"Request payload for project-template-manifests.\",\n  \"externalReferences\": [\n    {\n      \"externalSystem\": \"crm\",\n      \"externalObject\": \"Project Template Manifests\",\n      \"externalId\": \"project-template-manifests_external_123\"\n    }\n  ]\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"set-template-manifest-availability","groupSlug":"project-template-manifests","navigationGroup":"Project Template Manifests","sampleCoverage":"static-complete","coverageDepth":"coverage-status","examplesMode":"static"}},"get":{"operationId":"getTemplateManifest","tags":["Project Template Manifests"],"summary":"Get one Project Template as a manifest","description":"Returns one organization Project Template converted into manifest shape with stages and items. The manifest carries paymentEventMarks (event key + step name).","x-required-scopes":[],"responses":{"200":{"description":"Project Template manifest detail","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Template identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getTemplateManifest","x-llm-guidance":"Get one Project Template as a manifest. Use any valid organization API key. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/manifests/templates/$SOLAROS_TEMPLATE\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/manifests/templates/${process.env.SOLAROS_TEMPLATE}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/manifests/templates/{os.environ['SOLAROS_TEMPLATE']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-template-manifest","groupSlug":"project-template-manifests","navigationGroup":"Project Template Manifests","sampleCoverage":"static-complete","coverageDepth":"coverage-status","examplesMode":"static"}}},"/manifests/validate":{"post":{"operationId":"validateTemplateManifest","tags":["Project Template Manifests"],"summary":"Validate a Project Template manifest","description":"Validates a manifest payload and returns structured validation errors or manifest statistics without creating a template.","x-required-scopes":[],"responses":{"200":{"description":"Manifest validation result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for validateTemplateManifest.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"properties":{"name":{"type":"string"},"stages":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"name":{"type":"string"},"items":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"type":{"type":"string"},"title":{"type":"string"}}}}}}}}},"examples":{"validatetemplatemanifestRequest":{"value":{"name":"Residential PV install","stages":[{"name":"Install","items":[{"type":"WORK_ORDER","title":"Install array"}]}]}}}}}},"x-tool-name":"orgApi.validateTemplateManifest","x-llm-guidance":"Validate a Project Template manifest. Use any valid organization API key. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/manifests/validate\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"name\":\"Residential PV install\",\"stages\":[{\"name\":\"Install\",\"items\":[{\"type\":\"WORK_ORDER\",\"title\":\"Install array\"}]}]}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/manifests/validate`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"name\": \"Residential PV install\",\n    \"stages\": [\n      {\n        \"name\": \"Install\",\n        \"items\": [\n          {\n            \"type\": \"WORK_ORDER\",\n            \"title\": \"Install array\"\n          }\n        ]\n      }\n    ]\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/manifests/validate\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"name\": \"Residential PV install\",\n  \"stages\": [\n    {\n      \"name\": \"Install\",\n      \"items\": [\n        {\n          \"type\": \"WORK_ORDER\",\n          \"title\": \"Install array\"\n        }\n      ]\n    }\n  ]\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"validate-template-manifest","groupSlug":"project-template-manifests","navigationGroup":"Project Template Manifests","sampleCoverage":"static-complete","coverageDepth":"coverage-status","examplesMode":"static"}}},"/leads":{"get":{"operationId":"listLeads","tags":["Leads"],"summary":"List Leads","description":"Lists Leads for the authenticated organization with cursor pagination, endpoint-declared filters and sorting, exact custom Field filters using customFields.<savedIdentity>, hydrated customFields, and External References. Supply externalSystem, externalObject, and externalId together to filter by a canonical External Reference. Required scope: leads:read.","x-required-scopes":["leads:read"],"parameters":[{"name":"limit","in":"query","description":"Maximum number of Leads to return. Values above 100 are capped at 100.","schema":{"type":"integer","maximum":100}},{"name":"cursor","in":"query","description":"Opaque pagination cursor from the previous response meta.nextCursor value.","schema":{"type":"string"}},{"name":"status","in":"query","description":"Filter the list to Leads with a specific lifecycle status.","schema":{"type":"string","enum":["NEW","CONTACTED","QUALIFIED","UNQUALIFIED","CONVERTED"]}},{"name":"sourceId","in":"query","description":"Filter Leads by Lead Source id.","schema":{"type":"string"}},{"name":"campaignId","in":"query","description":"Filter Leads by Campaign id.","schema":{"type":"string"}},{"name":"salesTypeId","in":"query","description":"Filter Leads by one assigned Sales Type id.","schema":{"type":"string"}},{"name":"ownerId","in":"query","description":"Filter Leads by owner Team Member id.","schema":{"type":"string"}},{"name":"sortBy","in":"query","description":"Lead field used for ordering the list response.","schema":{"type":"string","enum":["createdAt","updatedAt","status"]}},{"name":"sortDir","in":"query","description":"Sort direction for the selected sortBy field.","schema":{"type":"string","enum":["asc","desc"]}},{"name":"externalSystem","in":"query","required":false,"description":"External Reference system filter. Supply with externalObject and externalId for exact reconciliation lookup.","schema":{"type":"string"}},{"name":"externalObject","in":"query","required":false,"description":"External Reference object filter. Supply with externalSystem and externalId.","schema":{"type":"string"}},{"name":"externalId","in":"query","required":false,"description":"External Reference id filter. Supply with externalSystem and externalObject.","schema":{"type":"string"}}],"responses":{"200":{"description":"Lead list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"400":{"description":"Unsupported filter or sort","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing leads:read scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.listLeads","x-llm-guidance":"List Leads. Use an organization API key with leads:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/leads\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/leads`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/leads\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-leads","groupSlug":"leads","navigationGroup":"Leads","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"post":{"operationId":"createLead","tags":["Leads"],"summary":"Create a Lead","description":"Creates one Lead for the authenticated organization, including website form submissions and external CRM imports. Requires Idempotency-Key. Supports Campaign attribution, Sales Type assignment, Lead Source, owner/default-owner assignment, an Originator (the owner is credited when originatorId is omitted), standard contact/address fields, customFields, and External References. Use /v1/schema before calling to discover valid customFields and required Field values. External References are created transactionally and conflicts return 409. Side effects include API actor ActivityLog, domain outbox event, idempotency capture, and usage telemetry. Required scope: leads:write.","x-required-scopes":["leads:write"],"x-idempotency-key":"required","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadCreateRequest"},"examples":{"websiteLeadForm":{"value":{"firstName":"Ada","lastName":"Lovelace","email":"ada@example.com","phone":"+15555550123","address":"1 Market St","city":"San Francisco","state":"CA","zipCode":"94105","sourceId":"source_website","campaignId":"campaign_spring_2026","salesTypeIds":["sales_type_install"],"notes":"Submitted the rooftop solar estimate form.","customFields":{"roofType":"tile"},"externalReferences":[{"externalSystem":"website","externalObject":"ContactFormSubmission","externalId":"form_submission_123","metadata":{"page":"/solar-estimate"}}]}},"leadWithCustomFields":{"value":{"firstName":"Ada","lastName":"Lovelace","email":"ada@example.com","ownerId":"team_member_123","sourceId":"source_123","customFields":{"roofType":"tile"},"externalReferences":[{"externalSystem":"salesforce","externalObject":"Lead","externalId":"00Q123"}]}}}}},"description":"JSON request payload for createLead."},"responses":{"201":{"description":"Created Lead envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadEnvelope"}}}},"400":{"description":"Validation, ownership, idempotency, or custom Field error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: leads:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Idempotency or External Reference conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.createLead","x-llm-guidance":"Create a Lead. Use an organization API key with leads:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/leads\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"firstName\":\"Ada\",\"lastName\":\"Lovelace\",\"email\":\"ada@example.com\",\"phone\":\"+15555550123\",\"address\":\"1 Market St\",\"city\":\"San Francisco\",\"state\":\"CA\",\"zipCode\":\"94105\",\"sourceId\":\"source_website\",\"campaignId\":\"campaign_spring_2026\",\"salesTypeIds\":[\"sales_type_install\"],\"notes\":\"Submitted the rooftop solar estimate form.\",\"customFields\":{\"roofType\":\"tile\"},\"externalReferences\":[{\"externalSystem\":\"website\",\"externalObject\":\"ContactFormSubmission\",\"externalId\":\"form_submission_123\",\"metadata\":{\"page\":\"/solar-estimate\"}}]}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/leads`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"firstName\": \"Ada\",\n    \"lastName\": \"Lovelace\",\n    \"email\": \"ada@example.com\",\n    \"phone\": \"+15555550123\",\n    \"address\": \"1 Market St\",\n    \"city\": \"San Francisco\",\n    \"state\": \"CA\",\n    \"zipCode\": \"94105\",\n    \"sourceId\": \"source_website\",\n    \"campaignId\": \"campaign_spring_2026\",\n    \"salesTypeIds\": [\n      \"sales_type_install\"\n    ],\n    \"notes\": \"Submitted the rooftop solar estimate form.\",\n    \"customFields\": {\n      \"roofType\": \"tile\"\n    },\n    \"externalReferences\": [\n      {\n        \"externalSystem\": \"website\",\n        \"externalObject\": \"ContactFormSubmission\",\n        \"externalId\": \"form_submission_123\",\n        \"metadata\": {\n          \"page\": \"/solar-estimate\"\n        }\n      }\n    ]\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/leads\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"firstName\": \"Ada\",\n  \"lastName\": \"Lovelace\",\n  \"email\": \"ada@example.com\",\n  \"phone\": \"+15555550123\",\n  \"address\": \"1 Market St\",\n  \"city\": \"San Francisco\",\n  \"state\": \"CA\",\n  \"zipCode\": \"94105\",\n  \"sourceId\": \"source_website\",\n  \"campaignId\": \"campaign_spring_2026\",\n  \"salesTypeIds\": [\n    \"sales_type_install\"\n  ],\n  \"notes\": \"Submitted the rooftop solar estimate form.\",\n  \"customFields\": {\n    \"roofType\": \"tile\"\n  },\n  \"externalReferences\": [\n    {\n      \"externalSystem\": \"website\",\n      \"externalObject\": \"ContactFormSubmission\",\n      \"externalId\": \"form_submission_123\",\n      \"metadata\": {\n        \"page\": \"/solar-estimate\"\n      }\n    }\n  ]\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-lead","groupSlug":"leads","navigationGroup":"Leads","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/leads/{id}":{"get":{"operationId":"getLead","tags":["Leads"],"summary":"Get one Lead","description":"Returns one Lead by solarOS id inside the authenticated organization boundary. Missing or cross-tenant records return 404. Required scope: leads:read.","x-required-scopes":["leads:read"],"responses":{"200":{"description":"Lead detail envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LeadEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: leads:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Lead not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Lead identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getLead","x-llm-guidance":"Get one Lead. Use an organization API key with leads:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/leads/$SOLAROS_LEAD\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/leads/${process.env.SOLAROS_LEAD}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/leads/{os.environ['SOLAROS_LEAD']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-lead","groupSlug":"leads","navigationGroup":"Leads","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"patch":{"operationId":"updateLead","tags":["Leads"],"summary":"Update one Lead","description":"Updates standard Lead fields, customFields, and the Originator using a typed partial object. originatorId credits a different Team Member, logged as an Originator change with its own lead.updated event. No-op updates return changed=false and do not write audit rows, domain events, or timestamp churn. Required scope: leads:write.","x-required-scopes":["leads:write"],"responses":{"200":{"description":"Updated Lead envelope with changed metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation or custom Field error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: leads:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Lead not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Lead identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for updateLead.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":["string","null"],"format":"email"},"phone":{"type":["string","null"]},"address":{"type":["string","null"]},"city":{"type":["string","null"]},"state":{"type":["string","null"]},"zipCode":{"type":["string","null"]},"sourceId":{"type":["string","null"]},"campaignId":{"type":["string","null"]},"salesTypeIds":{"type":"array","items":{"type":"string"}},"notes":{"type":["string","null"]},"status":{"type":"string","enum":["NEW","CONTACTED","QUALIFIED","UNQUALIFIED"]},"originatorId":{"type":"string","description":"Credits a different active or draft same-organization Team Member, and writes its own activity entry and updated event. An Originator cannot be cleared. Naming a deactivated Team Member is refused unless they are already the Originator."},"customFields":{"type":"object","additionalProperties":true,"description":"Field Values keyed by savedIdentity from GET /api/v1/schema."}}},"examples":{"updateleadRequest":{"value":{"status":"QUALIFIED","customFields":{"roofType":"metal"}}}}}}},"x-tool-name":"orgApi.updateLead","x-llm-guidance":"Update one Lead. Use an organization API key with leads:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/leads/$SOLAROS_LEAD\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"status\":\"QUALIFIED\",\"customFields\":{\"roofType\":\"metal\"}}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/leads/${process.env.SOLAROS_LEAD}`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"status\": \"QUALIFIED\",\n    \"customFields\": {\n      \"roofType\": \"metal\"\n    }\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/leads/{os.environ['SOLAROS_LEAD']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"status\": \"QUALIFIED\",\n  \"customFields\": {\n    \"roofType\": \"metal\"\n  }\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"update-lead","groupSlug":"leads","navigationGroup":"Leads","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"delete":{"operationId":"deleteLead","tags":["Leads"],"summary":"Delete one Lead","description":"Deletes one tenant-scoped Lead and its public API sidecars such as custom Field Values and External References. Missing or cross-tenant records return 404. Required scope: leads:delete.","x-required-scopes":["leads:delete"],"responses":{"200":{"description":"Lead delete action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: leads:delete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Lead not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Lead identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.deleteLead","x-llm-guidance":"Delete one Lead. Use an organization API key with leads:delete. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X DELETE \"$SOLAROS_BASE_URL/api/v1/leads/$SOLAROS_LEAD\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/leads/${process.env.SOLAROS_LEAD}`, {\n  method: 'DELETE',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"DELETE\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/leads/{os.environ['SOLAROS_LEAD']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"delete-lead","groupSlug":"leads","navigationGroup":"Leads","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/leads/{id}/convert":{"post":{"operationId":"convertLead","tags":["Leads"],"summary":"Convert one Lead","description":"Converts a Lead into a Customer, Property, and Opportunity using the documented email and placeId identity rules: a placeId reuses the Customer's own Property at that place, and otherwise the Customer gets a new Property. The Opportunity takes the Lead's Originator, returned as result.opportunity.originatorId. On a Property already on file, this organization becomes its primary service provider only when no organization is. Requires Idempotency-Key. Required scope: leads:convert.","x-required-scopes":["leads:convert"],"x-idempotency-key":"required","responses":{"201":{"description":"Lead conversion action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"400":{"description":"Validation or ownership error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: leads:convert","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Lead not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Lead already converted or idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Lead identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for convertLead.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["customer","property","opportunity"],"properties":{"customer":{"type":"object","additionalProperties":false,"required":["firstName","lastName","email"],"properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":["string","null"]},"displayName":{"type":["string","null"]}}},"property":{"type":"object","additionalProperties":false,"required":["address","city","state","zipCode"],"properties":{"address":{"type":"string"},"city":{"type":"string"},"state":{"type":"string","description":"US state name or abbreviation; normalized by solarOS."},"zipCode":{"type":"string"},"placeId":{"type":["string","null"]},"latitude":{"type":["number","null"]},"longitude":{"type":["number","null"]},"formattedAddress":{"type":["string","null"]},"country":{"type":"string"}}},"opportunity":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"value":{"type":["string","number","null"]},"expectedCloseDate":{"type":["string","null"]},"ownerId":{"type":["string","null"],"description":"Active or draft same-organization Team Member id. When omitted, the API key default owner for this resource is used. Ownership cannot be changed through generic PATCH endpoints."},"notes":{"type":["string","null"]},"salesTypeIds":{"type":"array","items":{"type":"string"}}}}}},"examples":{"convertleadRequest":{"value":{"customer":{"firstName":"Ada","lastName":"Lovelace","email":"ada@example.com"},"property":{"address":"1 Market St","city":"San Francisco","state":"CA","zipCode":"94105"},"opportunity":{"name":"Residential solar consultation","salesTypeIds":["sales_type_install"]}}}}}}},"x-tool-name":"orgApi.convertLead","x-llm-guidance":"Convert one Lead. Use an organization API key with leads:convert. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/leads/$SOLAROS_LEAD/convert\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"customer\":{\"firstName\":\"Ada\",\"lastName\":\"Lovelace\",\"email\":\"ada@example.com\"},\"property\":{\"address\":\"1 Market St\",\"city\":\"San Francisco\",\"state\":\"CA\",\"zipCode\":\"94105\"},\"opportunity\":{\"name\":\"Residential solar consultation\",\"salesTypeIds\":[\"sales_type_install\"]}}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/leads/${process.env.SOLAROS_LEAD}/convert`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"customer\": {\n      \"firstName\": \"Ada\",\n      \"lastName\": \"Lovelace\",\n      \"email\": \"ada@example.com\"\n    },\n    \"property\": {\n      \"address\": \"1 Market St\",\n      \"city\": \"San Francisco\",\n      \"state\": \"CA\",\n      \"zipCode\": \"94105\"\n    },\n    \"opportunity\": {\n      \"name\": \"Residential solar consultation\",\n      \"salesTypeIds\": [\n        \"sales_type_install\"\n      ]\n    }\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/leads/{os.environ['SOLAROS_LEAD']}/convert\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"customer\": {\n    \"firstName\": \"Ada\",\n    \"lastName\": \"Lovelace\",\n    \"email\": \"ada@example.com\"\n  },\n  \"property\": {\n    \"address\": \"1 Market St\",\n    \"city\": \"San Francisco\",\n    \"state\": \"CA\",\n    \"zipCode\": \"94105\"\n  },\n  \"opportunity\": {\n    \"name\": \"Residential solar consultation\",\n    \"salesTypeIds\": [\n      \"sales_type_install\"\n    ]\n  }\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"convert-lead","groupSlug":"leads","navigationGroup":"Leads","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/customers":{"get":{"operationId":"listCustomers","tags":["Customers"],"summary":"List Customers","description":"Lists Customers available to the calling organization with safe identity fields, organization-specific details (including billingEmail), customFields, and External References. Supply externalSystem, externalObject, and externalId together to filter by a canonical External Reference. Required scope: customers:read.","x-required-scopes":["customers:read"],"parameters":[{"name":"limit","in":"query","required":false,"description":"Maximum records to return. Defaults to 50 and is capped at 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Opaque record cursor from the previous response meta.nextCursor value.","schema":{"type":"string"}},{"name":"sortBy","in":"query","required":false,"description":"Customer sort field. Defaults to createdAt.","schema":{"type":"string","enum":["createdAt","updatedAt","displayName"]}},{"name":"sortDir","in":"query","required":false,"description":"Sort direction. Defaults to desc.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"ownerId","in":"query","required":false,"description":"Filter by the Customer Relationship owner id.","schema":{"type":"string"}},{"name":"phone","in":"query","required":false,"description":"Find Customers by phone. Formatting is ignored, and the last ten digits must match the Customer's phone or this organization's phone for them, so (707) 555-1234 and +17075551234 are the same number. An empty value, or one with no digits, matches no Customer. With email, a Customer must match both.","schema":{"type":"string"}},{"name":"email","in":"query","required":false,"description":"Find Customers by email, ignoring case and surrounding spaces. Matches the Customer's email or this organization's email for them, and the email of a Customer merged into them. An empty value matches no Customer; before 2026-10-15 it matched Customers saved with an empty email. With phone, a Customer must match both.","schema":{"type":"string"}},{"name":"externalSystem","in":"query","required":false,"description":"External Reference system filter. Supply with externalObject and externalId for exact reconciliation lookup.","schema":{"type":"string"}},{"name":"externalObject","in":"query","required":false,"description":"External Reference object filter. Supply with externalSystem and externalId.","schema":{"type":"string"}},{"name":"externalId","in":"query","required":false,"description":"External Reference id filter. Supply with externalSystem and externalObject.","schema":{"type":"string"}}],"responses":{"200":{"description":"Customer list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: customers:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.listCustomers","x-llm-guidance":"List Customers. Use an organization API key with customers:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/customers\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/customers`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/customers\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-customers","groupSlug":"customers","navigationGroup":"Customers","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"post":{"operationId":"createCustomer","tags":["Customers"],"summary":"Create or link a Customer","description":"Creates or links a Customer for the calling organization. An email matches only a Customer this organization already serves, or one it deleted, which restores them; the email of a merged Customer follows the Customer it was merged into. An email held by a Customer this organization does not serve gets its own record holding only what was sent, and the response reads the same as a new Customer. Requires Idempotency-Key. Required scope: customers:write.","x-required-scopes":["customers:write"],"x-idempotency-key":"required","responses":{"201":{"description":"Customer envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation, ownership, idempotency, or custom Field error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: customers:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"External Reference or idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for createCustomer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["firstName","lastName","email"],"properties":{"firstName":{"type":"string"},"lastName":{"type":"string"},"billingEmail":{"type":["string","null"],"description":"Invoice recipient for this organization. Blank or null uses the contact email.","anyOf":[{"type":"string","format":"email"},{"const":""},{"type":"null"}]},"email":{"type":"string","format":"email"},"phone":{"type":["string","null"]},"displayName":{"type":["string","null"]},"description":{"type":["string","null"]},"internalNotes":{"type":["string","null"]},"tags":{"type":["array","null"],"items":{"type":"string"}},"referralSource":{"type":["string","null"]},"ownerId":{"type":["string","null"],"description":"Active or draft same-organization Team Member id. When omitted, the API key default owner for this resource is used. Ownership cannot be changed through generic PATCH endpoints."},"customFields":{"type":"object","additionalProperties":true,"description":"Field Values keyed by savedIdentity from GET /api/v1/schema."},"externalReferences":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"examples":{"createcustomerRequest":{"value":{"firstName":"Ada","lastName":"Lovelace","email":"ada@example.com","phone":"+15555550123","customFields":{"preferredLanguage":"en"},"externalReferences":[{"externalSystem":"salesforce","externalObject":"Contact","externalId":"003123"}]}}}}}},"x-tool-name":"orgApi.createCustomer","x-llm-guidance":"Create or link a Customer. Use an organization API key with customers:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/customers\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"firstName\":\"Ada\",\"lastName\":\"Lovelace\",\"email\":\"ada@example.com\",\"phone\":\"+15555550123\",\"customFields\":{\"preferredLanguage\":\"en\"},\"externalReferences\":[{\"externalSystem\":\"salesforce\",\"externalObject\":\"Contact\",\"externalId\":\"003123\"}]}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/customers`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"firstName\": \"Ada\",\n    \"lastName\": \"Lovelace\",\n    \"email\": \"ada@example.com\",\n    \"phone\": \"+15555550123\",\n    \"customFields\": {\n      \"preferredLanguage\": \"en\"\n    },\n    \"externalReferences\": [\n      {\n        \"externalSystem\": \"salesforce\",\n        \"externalObject\": \"Contact\",\n        \"externalId\": \"003123\"\n      }\n    ]\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/customers\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"firstName\": \"Ada\",\n  \"lastName\": \"Lovelace\",\n  \"email\": \"ada@example.com\",\n  \"phone\": \"+15555550123\",\n  \"customFields\": {\n    \"preferredLanguage\": \"en\"\n  },\n  \"externalReferences\": [\n    {\n      \"externalSystem\": \"salesforce\",\n      \"externalObject\": \"Contact\",\n      \"externalId\": \"003123\"\n    }\n  ]\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-customer","groupSlug":"customers","navigationGroup":"Customers","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/customers/{id}":{"get":{"operationId":"getCustomer","tags":["Customers"],"summary":"Get one Customer","description":"Returns one Customer by id inside the calling organization boundary. The response includes billingEmail; null falls back to the contact email for invoicing. Missing or inaccessible shared Customers return 404.","x-required-scopes":["customers:read"],"responses":{"200":{"description":"Customer envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: customers:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Customer identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getCustomer","x-llm-guidance":"Get one Customer. Use an organization API key with customers:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/customers/$SOLAROS_CUSTOMER\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/customers/${process.env.SOLAROS_CUSTOMER}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/customers/{os.environ['SOLAROS_CUSTOMER']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-customer","groupSlug":"customers","navigationGroup":"Customers","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"patch":{"operationId":"updateCustomer","tags":["Customers"],"summary":"Update one Customer","description":"Updates organization-specific Customer profile fields and customFields. It does not mutate shared platform firstName, lastName, or email identity fields, and ownerId is rejected because Organization API v1 does not expose the staff reassignment action.","x-required-scopes":["customers:write"],"responses":{"200":{"description":"Updated Customer envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: customers:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Customer identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for updateCustomer.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"billingEmail":{"type":["string","null"],"description":"Invoice recipient for this organization. Blank or null uses the contact email.","anyOf":[{"type":"string","format":"email"},{"const":""},{"type":"null"}]},"displayName":{"type":["string","null"]},"emailOverride":{"type":["string","null"],"format":"email"},"phoneOverride":{"type":["string","null"]},"description":{"type":["string","null"]},"internalNotes":{"type":["string","null"]},"tags":{"type":["array","null"],"items":{"type":"string"}},"referralSource":{"type":["string","null"]},"customFields":{"type":"object","additionalProperties":true,"description":"Field Values keyed by savedIdentity from GET /api/v1/schema."}}},"examples":{"updatecustomerRequest":{"value":{"internalNotes":"Prefers afternoon calls.","customFields":{"preferredLanguage":"en"}}}}}}},"x-tool-name":"orgApi.updateCustomer","x-llm-guidance":"Update one Customer. Use an organization API key with customers:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/customers/$SOLAROS_CUSTOMER\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"internalNotes\":\"Prefers afternoon calls.\",\"customFields\":{\"preferredLanguage\":\"en\"}}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/customers/${process.env.SOLAROS_CUSTOMER}`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"internalNotes\": \"Prefers afternoon calls.\",\n    \"customFields\": {\n      \"preferredLanguage\": \"en\"\n    }\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/customers/{os.environ['SOLAROS_CUSTOMER']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"internalNotes\": \"Prefers afternoon calls.\",\n  \"customFields\": {\n    \"preferredLanguage\": \"en\"\n  }\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"update-customer","groupSlug":"customers","navigationGroup":"Customers","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/customer-relationships":{"post":{"operationId":"createCustomerRelationship","tags":["Customer Relationships"],"summary":"Create or update a Customer Relationship","description":"Creates or updates the organization-scoped Customer Relationship sidecar for a Customer this organization already serves, or one it deleted, which restores them. firstName, lastName, and phone change the shared Customer only when this organization alone holds that Customer and it has no portal account. Otherwise they are saved on this relationship, read back as displayName and phone, and the shared Customer and every other organization stay as they were. Returns 404 when the Customer does not exist or was merged into another. Requires Idempotency-Key. Required scope: customers:write.","x-required-scopes":["customers:write"],"x-idempotency-key":"required","responses":{"201":{"description":"Customer Relationship envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: customers:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for createCustomerRelationship.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["customerId"],"properties":{"customerId":{"type":"string"},"customerSalesforceAccountId":{"type":["string","null"]},"billingEmail":{"type":["string","null"],"description":"Invoice recipient for this organization. Blank or null uses the contact email.","anyOf":[{"type":"string","format":"email"},{"const":""},{"type":"null"}]},"email":{"type":["string","null"],"format":"email"},"firstName":{"type":["string","null"]},"lastName":{"type":["string","null"]},"ownerTeamMemberId":{"type":["string","null"],"description":"Active or draft same-organization Team Member id. When omitted, the API key default owner for this resource is used. Ownership cannot be changed through generic PATCH endpoints."},"phone":{"type":["string","null"]},"externalReferences":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"examples":{"createcustomerrelationshipRequest":{"value":{"customerId":"customer_123","ownerTeamMemberId":"team_member_123"}}}}}},"x-tool-name":"orgApi.createCustomerRelationship","x-llm-guidance":"Create or update a Customer Relationship. Use an organization API key with customers:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/customer-relationships\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"customerId\":\"customer_123\",\"ownerTeamMemberId\":\"team_member_123\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/customer-relationships`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"customerId\": \"customer_123\",\n    \"ownerTeamMemberId\": \"team_member_123\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/customer-relationships\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"customerId\": \"customer_123\",\n  \"ownerTeamMemberId\": \"team_member_123\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-customer-relationship","groupSlug":"customer-relationships","navigationGroup":"Customer Relationships","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/customer-relationships/{id}":{"get":{"operationId":"getCustomerRelationship","tags":["Customer Relationships"],"summary":"Get one Customer Relationship","description":"Returns one organization-scoped Customer Relationship by relationship id. Required scope: customers:read.","x-required-scopes":["customers:read"],"responses":{"200":{"description":"Customer Relationship envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: customers:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Customer Relationship identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getCustomerRelationship","x-llm-guidance":"Get one Customer Relationship. Use an organization API key with customers:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/customer-relationships/$SOLAROS_CUSTOMER_RELATIONSHIP\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/customer-relationships/${process.env.SOLAROS_CUSTOMER_RELATIONSHIP}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/customer-relationships/{os.environ['SOLAROS_CUSTOMER_RELATIONSHIP']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-customer-relationship","groupSlug":"customer-relationships","navigationGroup":"Customer Relationships","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"patch":{"operationId":"updateCustomerRelationship","tags":["Customer Relationships"],"summary":"Update one Customer Relationship","description":"Updates relationship contact mirrors by relationship id. firstName, lastName, and phone change the shared Customer only when this organization alone holds that Customer and it has no portal account. Otherwise they are saved on this relationship, read back as displayName and phone, and the shared Customer and every other organization stay as they were. ownerTeamMemberId is create-only here and is rejected on PATCH because Organization API v1 does not expose the staff reassignment action. Required scope: customers:write.","x-required-scopes":["customers:write"],"responses":{"200":{"description":"Updated Customer Relationship envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: customers:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Customer Relationship identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for updateCustomerRelationship.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"customerSalesforceAccountId":{"type":["string","null"]},"billingEmail":{"type":["string","null"],"description":"Invoice recipient for this organization. Blank or null uses the contact email.","anyOf":[{"type":"string","format":"email"},{"const":""},{"type":"null"}]},"email":{"type":["string","null"],"format":"email"},"firstName":{"type":["string","null"]},"lastName":{"type":["string","null"]},"phone":{"type":["string","null"]}}},"examples":{"updatecustomerrelationshipRequest":{"value":{"phone":"+15555550124"}}}}}},"x-tool-name":"orgApi.updateCustomerRelationship","x-llm-guidance":"Update one Customer Relationship. Use an organization API key with customers:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/customer-relationships/$SOLAROS_CUSTOMER_RELATIONSHIP\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"phone\":\"+15555550124\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/customer-relationships/${process.env.SOLAROS_CUSTOMER_RELATIONSHIP}`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"phone\": \"+15555550124\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/customer-relationships/{os.environ['SOLAROS_CUSTOMER_RELATIONSHIP']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"phone\": \"+15555550124\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"update-customer-relationship","groupSlug":"customer-relationships","navigationGroup":"Customer Relationships","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/properties":{"get":{"operationId":"listProperties","tags":["Properties"],"summary":"List Properties","description":"Lists Properties linked to the calling organization. Supply externalSystem, externalObject, and externalId together to filter by a canonical External Reference. Required scope: properties:read.","x-required-scopes":["properties:read"],"parameters":[{"name":"limit","in":"query","required":false,"description":"Maximum records to return. Defaults to 50 and is capped at 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Opaque record cursor from the previous response meta.nextCursor value.","schema":{"type":"string"}},{"name":"sortDir","in":"query","required":false,"description":"Sort direction. Defaults to desc.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"customerId","in":"query","required":false,"description":"Filter by Customer id.","schema":{"type":"string"}},{"name":"externalSystem","in":"query","required":false,"description":"External Reference system filter. Supply with externalObject and externalId for exact reconciliation lookup.","schema":{"type":"string"}},{"name":"externalObject","in":"query","required":false,"description":"External Reference object filter. Supply with externalSystem and externalId.","schema":{"type":"string"}},{"name":"externalId","in":"query","required":false,"description":"External Reference id filter. Supply with externalSystem and externalObject.","schema":{"type":"string"}}],"responses":{"200":{"description":"Property list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: properties:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.listProperties","x-llm-guidance":"List Properties. Use an organization API key with properties:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/properties\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/properties`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/properties\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-properties","groupSlug":"properties","navigationGroup":"Properties","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"post":{"operationId":"createProperty","tags":["Properties"],"summary":"Create or link a Property","description":"Creates a Property for the Customer, or links that Customer's own Property at an exact placeId match to the calling organization, without fuzzy matching. A Property at the same place under another Customer is never returned or linked; this Customer gets a new Property. customFields accepts any active Field; an answer to a Property Field (see isPropertyField) becomes the Property's answer, is recorded in its history, and fills that Field on the Property's draft Quotes and open Projects where it is still blank. isPrimary asks for this organization to be the Property's primary service provider and defaults to true. A new Property takes it as sent. On a Property already on file it applies only when no organization is primary; the link succeeds either way, so read access.isPrimary on the response for the outcome. It has no effect when this organization already has access. Requires Idempotency-Key. Required scope: properties:write.","x-required-scopes":["properties:write"],"x-idempotency-key":"required","responses":{"201":{"description":"Property envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: properties:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Customer not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for createProperty.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["customerId","address","city","state","zipCode"],"properties":{"customerId":{"type":"string"},"address":{"type":"string"},"city":{"type":"string"},"state":{"type":"string"},"zipCode":{"type":"string"},"placeId":{"type":["string","null"]},"latitude":{"type":["number","null"]},"longitude":{"type":["number","null"]},"formattedAddress":{"type":["string","null"]},"country":{"type":"string"},"serviceTypes":{"type":"array","items":{"type":"string"}},"isPrimary":{"type":"boolean"},"customFields":{"type":"object","additionalProperties":true,"description":"Field Values keyed by savedIdentity from GET /api/v1/schema."},"externalReferences":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"examples":{"createpropertyRequest":{"value":{"customerId":"customer_123","address":"1 Market St","city":"San Francisco","state":"CA","zipCode":"94105","country":"US","serviceTypes":["SOLAR"]}}}}}},"x-tool-name":"orgApi.createProperty","x-llm-guidance":"Create or link a Property. Use an organization API key with properties:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/properties\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"customerId\":\"customer_123\",\"address\":\"1 Market St\",\"city\":\"San Francisco\",\"state\":\"CA\",\"zipCode\":\"94105\",\"country\":\"US\",\"serviceTypes\":[\"SOLAR\"]}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/properties`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"customerId\": \"customer_123\",\n    \"address\": \"1 Market St\",\n    \"city\": \"San Francisco\",\n    \"state\": \"CA\",\n    \"zipCode\": \"94105\",\n    \"country\": \"US\",\n    \"serviceTypes\": [\n      \"SOLAR\"\n    ]\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/properties\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"customerId\": \"customer_123\",\n  \"address\": \"1 Market St\",\n  \"city\": \"San Francisco\",\n  \"state\": \"CA\",\n  \"zipCode\": \"94105\",\n  \"country\": \"US\",\n  \"serviceTypes\": [\n    \"SOLAR\"\n  ]\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-property","groupSlug":"properties","navigationGroup":"Properties","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/properties/{id}":{"get":{"operationId":"getProperty","tags":["Properties"],"summary":"Get one Property","x-required-scopes":["properties:read"],"responses":{"200":{"description":"Property envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: properties:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"description":"Get one Property","parameters":[{"name":"id","in":"path","required":true,"description":"Property identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getProperty","x-llm-guidance":"Get one Property. Use an organization API key with properties:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/properties/$SOLAROS_PROPERTY\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/properties/${process.env.SOLAROS_PROPERTY}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/properties/{os.environ['SOLAROS_PROPERTY']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-property","groupSlug":"properties","navigationGroup":"Properties","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/properties/{id}/media/links":{"post":{"operationId":"createPropertyMediaLink","tags":["Properties"],"summary":"Add a Link/URL file to a Property","description":"Creates a text/uri-list media asset and Property association, or returns the existing live association for the same normalized URL. Requires active Property access, properties:write, and Idempotency-Key. URLs are stored without fetching their contents.","x-required-scopes":["properties:write"],"x-idempotency-key":"required","responses":{"200":{"description":"Existing Property media link envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"201":{"description":"Created Property media link envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Invalid URL, filename, or missing idempotency key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: properties:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Property not found or inaccessible","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Idempotency conflict or URL already stored as a file","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Property identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for createPropertyMediaLink.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["url","filename"],"properties":{"url":{"type":"string","format":"uri","maxLength":8192,"description":"HTTP(S) URL without credentials. Trimmed and normalized before deduplication."},"filename":{"type":"string","minLength":1,"maxLength":255,"description":"Display name without slashes or control characters."}}},"examples":{"createpropertymedialinkRequest":{"value":{"url":"https://drive.google.com/drive/folders/installation-folder","filename":"Installation Drive Folder: P-19552"}}}}}},"x-tool-name":"orgApi.createPropertyMediaLink","x-llm-guidance":"Add a Link/URL file to a Property. Use an organization API key with properties:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/properties/$SOLAROS_PROPERTY/media/links\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"url\":\"https://drive.google.com/drive/folders/installation-folder\",\"filename\":\"Installation Drive Folder: P-19552\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/properties/${process.env.SOLAROS_PROPERTY}/media/links`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"url\": \"https://drive.google.com/drive/folders/installation-folder\",\n    \"filename\": \"Installation Drive Folder: P-19552\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/properties/{os.environ['SOLAROS_PROPERTY']}/media/links\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"url\": \"https://drive.google.com/drive/folders/installation-folder\",\n  \"filename\": \"Installation Drive Folder: P-19552\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-property-media-link","groupSlug":"properties","navigationGroup":"Properties","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/opportunities":{"get":{"operationId":"listOpportunities","tags":["Opportunities"],"summary":"List Opportunities","description":"Lists Opportunities inside the organization and linked Property boundary. Supply externalSystem, externalObject, and externalId together to filter by a canonical External Reference. Required scope: opportunities:read.","x-required-scopes":["opportunities:read"],"parameters":[{"name":"limit","in":"query","required":false,"description":"Maximum records to return. Defaults to 50 and is capped at 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Opaque record cursor from the previous response meta.nextCursor value.","schema":{"type":"string"}},{"name":"sortDir","in":"query","required":false,"description":"Sort direction. Defaults to desc.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"stage","in":"query","required":false,"description":"Filter by the current Opportunity stage.","schema":{"type":"string","enum":["NEW","PROPOSAL","NEGOTIATION","CLOSED_WON","CLOSED_LOST"]}},{"name":"customerId","in":"query","required":false,"description":"Filter by Customer id.","schema":{"type":"string"}},{"name":"propertyId","in":"query","required":false,"description":"Filter by accessible Property id.","schema":{"type":"string"}},{"name":"ownerId","in":"query","required":false,"description":"Filter by owner Team Member id.","schema":{"type":"string"}},{"name":"externalSystem","in":"query","required":false,"description":"External Reference system filter. Supply with externalObject and externalId for exact reconciliation lookup.","schema":{"type":"string"}},{"name":"externalObject","in":"query","required":false,"description":"External Reference object filter. Supply with externalSystem and externalId.","schema":{"type":"string"}},{"name":"externalId","in":"query","required":false,"description":"External Reference id filter. Supply with externalSystem and externalObject.","schema":{"type":"string"}}],"responses":{"200":{"description":"Opportunity list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: opportunities:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.listOpportunities","x-llm-guidance":"List Opportunities. Use an organization API key with opportunities:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/opportunities\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/opportunities`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/opportunities\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-opportunities","groupSlug":"opportunities","navigationGroup":"Opportunities","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"post":{"operationId":"createOpportunity","tags":["Opportunities"],"summary":"Create an Opportunity","description":"Creates an Opportunity for an accessible Customer. propertyId is optional for external CRM imports that do not yet have a solarOS Property mapping. Stage changes do not create hidden downstream records. Without originatorId, the owner is credited with bringing the sale in. Requires Idempotency-Key.","x-required-scopes":["opportunities:write"],"x-idempotency-key":"required","responses":{"201":{"description":"Opportunity envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: opportunities:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Customer or Property not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for createOpportunity.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","customerId"],"properties":{"name":{"type":"string"},"customerId":{"type":"string"},"propertyId":{"type":["string","null"]},"value":{"type":["string","number","null"]},"stage":{"type":"string","enum":["NEW","PROPOSAL","NEGOTIATION","CLOSED_WON","CLOSED_LOST"]},"expectedCloseDate":{"type":["string","null"]},"ownerId":{"type":["string","null"],"description":"Active or draft same-organization Team Member id. When omitted, the API key default owner for this resource is used. Ownership cannot be changed through generic PATCH endpoints."},"originatorId":{"type":["string","null"],"description":"The active or draft same-organization Team Member credited with bringing this sale in. When omitted, the owner is credited."},"notes":{"type":["string","null"]},"customFields":{"type":"object","additionalProperties":true,"description":"Field Values keyed by savedIdentity from GET /api/v1/schema."},"externalReferences":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"examples":{"createopportunityRequest":{"value":{"customerId":"customer_123","propertyId":"property_123","name":"Residential solar install","stage":"PROPOSAL","value":"42500","expectedCloseDate":"2026-09-15"}}}}}},"x-tool-name":"orgApi.createOpportunity","x-llm-guidance":"Create an Opportunity. Use an organization API key with opportunities:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/opportunities\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"customerId\":\"customer_123\",\"propertyId\":\"property_123\",\"name\":\"Residential solar install\",\"stage\":\"PROPOSAL\",\"value\":\"42500\",\"expectedCloseDate\":\"2026-09-15\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/opportunities`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"customerId\": \"customer_123\",\n    \"propertyId\": \"property_123\",\n    \"name\": \"Residential solar install\",\n    \"stage\": \"PROPOSAL\",\n    \"value\": \"42500\",\n    \"expectedCloseDate\": \"2026-09-15\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/opportunities\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"customerId\": \"customer_123\",\n  \"propertyId\": \"property_123\",\n  \"name\": \"Residential solar install\",\n  \"stage\": \"PROPOSAL\",\n  \"value\": \"42500\",\n  \"expectedCloseDate\": \"2026-09-15\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-opportunity","groupSlug":"opportunities","navigationGroup":"Opportunities","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/opportunities/{id}":{"get":{"operationId":"getOpportunity","tags":["Opportunities"],"summary":"Get one Opportunity","description":"Returns one organization-owned Opportunity, including opportunities that are Account-linked before a Property is mapped.","x-required-scopes":["opportunities:read"],"responses":{"200":{"description":"Opportunity envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: opportunities:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Opportunity identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getOpportunity","x-llm-guidance":"Get one Opportunity. Use an organization API key with opportunities:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/opportunities/$SOLAROS_OPPORTUNITY\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/opportunities/${process.env.SOLAROS_OPPORTUNITY}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/opportunities/{os.environ['SOLAROS_OPPORTUNITY']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-opportunity","groupSlug":"opportunities","navigationGroup":"Opportunities","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"patch":{"operationId":"updateOpportunity","tags":["Opportunities"],"summary":"Update one Opportunity","description":"Updates standard Opportunity fields, customFields, and the Originator. ownerId is create-only and is rejected on PATCH because Organization API v1 does not expose the staff reassignment action. originatorId credits a different Team Member, logged as an Originator change with its own opportunity.updated event; the Opportunity's Quotes keep the Originator they have. Quote lifecycle changes can also synchronize the linked Opportunity stage. No-op PATCH returns changed=false and does not emit audit/domain events.","x-required-scopes":["opportunities:write"],"responses":{"200":{"description":"Updated Opportunity envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation or ownership error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: opportunities:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Opportunity identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for updateOpportunity.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"propertyId":{"type":["string","null"]},"value":{"type":["string","number","null"]},"stage":{"type":"string","enum":["NEW","PROPOSAL","NEGOTIATION","CLOSED_WON","CLOSED_LOST"]},"expectedCloseDate":{"type":["string","null"]},"notes":{"type":["string","null"]},"originatorId":{"type":"string","description":"Credits a different active or draft same-organization Team Member, and writes its own activity entry and updated event. An Originator cannot be cleared. Naming a deactivated Team Member is refused unless they are already the Originator."},"customFields":{"type":"object","additionalProperties":true,"description":"Field Values keyed by savedIdentity from GET /api/v1/schema."}}},"examples":{"updateopportunityRequest":{"value":{"stage":"NEGOTIATION","value":"43500"}}}}}},"x-tool-name":"orgApi.updateOpportunity","x-llm-guidance":"Update one Opportunity. Use an organization API key with opportunities:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/opportunities/$SOLAROS_OPPORTUNITY\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"stage\":\"NEGOTIATION\",\"value\":\"43500\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/opportunities/${process.env.SOLAROS_OPPORTUNITY}`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"stage\": \"NEGOTIATION\",\n    \"value\": \"43500\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/opportunities/{os.environ['SOLAROS_OPPORTUNITY']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"stage\": \"NEGOTIATION\",\n  \"value\": \"43500\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"update-opportunity","groupSlug":"opportunities","navigationGroup":"Opportunities","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/team-members":{"get":{"operationId":"listTeamMembers","tags":["Team Members"],"summary":"List assignable Team Members","description":"Returns same-organization staff without sign-in credentials. Active assignable members are returned by default; status=inactive/all, salesforceUserId, and salesforceServiceResourceId filters are supported.","x-required-scopes":["team_members:read"],"parameters":[{"name":"status","in":"query","required":false,"description":"Filter Team Members by active, inactive, or all status.","schema":{"type":"string","enum":["active","inactive","all"]}},{"name":"salesforceUserId","in":"query","required":false,"description":"Filter by the Team Member's Salesforce User ID, set from an External Reference.","schema":{"type":"string"}},{"name":"salesforceServiceResourceId","in":"query","required":false,"description":"Filter by the Team Member's Salesforce Service Resource ID, set from an External Reference.","schema":{"type":"string"}}],"responses":{"200":{"description":"Team Member list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: team_members:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.listTeamMembers","x-llm-guidance":"List assignable Team Members. Use an organization API key with team_members:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/team-members\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/team-members`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/team-members\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-team-members","groupSlug":"team-members","navigationGroup":"Team Members","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"post":{"operationId":"createTeamMember","tags":["Team Members"],"summary":"Create or resolve a draft Team Member","description":"Creates a same-organization draft Team Member for external integrations, or returns an existing member matched by Salesforce identity, email, or External Reference. Draft Team Members can own imported records without being invited to sign in. Requires Idempotency-Key and team_members:write.","x-required-scopes":["team_members:write"],"x-idempotency-key":"required","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"email":{"type":["string","null"],"format":"email"},"firstName":{"type":["string","null"]},"lastName":{"type":["string","null"]},"displayName":{"type":["string","null"]},"phone":{"type":["string","null"]},"role":{"type":"string","enum":["OWNER","ADMIN","SALES_MANAGER","SALES_USER","OPERATIONS_MANAGER","OPERATIONS_USER","TECHNICIAN","MEMBER"]},"status":{"type":"string","const":"DRAFT"},"salesforceUserId":{"type":["string","null"]},"salesforceServiceResourceId":{"type":["string","null"]},"externalReferences":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"examples":{"createteammemberRequest":{"value":{"email":"technician@example.com","firstName":"Grace","lastName":"Hopper","role":"TECHNICIAN","status":"DRAFT"}}}}},"description":"JSON request payload for createTeamMember."},"responses":{"200":{"description":"Existing Team Member envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberEnvelope"}}}},"201":{"description":"Created draft Team Member envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberEnvelope"}}}},"400":{"description":"Validation or idempotency error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: team_members:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"External Reference/idempotency conflict, or SEAT_LIMIT_REACHED when schedulable=true exceeds included seats.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.createTeamMember","x-llm-guidance":"Create or resolve a draft Team Member. Use an organization API key with team_members:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/team-members\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"email\":\"technician@example.com\",\"firstName\":\"Grace\",\"lastName\":\"Hopper\",\"role\":\"TECHNICIAN\",\"status\":\"DRAFT\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/team-members`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"email\": \"technician@example.com\",\n    \"firstName\": \"Grace\",\n    \"lastName\": \"Hopper\",\n    \"role\": \"TECHNICIAN\",\n    \"status\": \"DRAFT\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/team-members\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"email\": \"technician@example.com\",\n  \"firstName\": \"Grace\",\n  \"lastName\": \"Hopper\",\n  \"role\": \"TECHNICIAN\",\n  \"status\": \"DRAFT\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-team-member","groupSlug":"team-members","navigationGroup":"Team Members","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/team-members/{id}":{"get":{"operationId":"getTeamMember","tags":["Team Members"],"summary":"Get one Team Member","description":"Returns one same-organization Team Member without sign-in credentials, including Salesforce identity mirrors. Required scope: team_members:read.","x-required-scopes":["team_members:read"],"responses":{"200":{"description":"Team Member envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamMemberEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: team_members:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Team Member identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getTeamMember","x-llm-guidance":"Get one Team Member. Use an organization API key with team_members:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/team-members/$SOLAROS_TEAM_MEMBER\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/team-members/${process.env.SOLAROS_TEAM_MEMBER}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/team-members/{os.environ['SOLAROS_TEAM_MEMBER']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-team-member","groupSlug":"team-members","navigationGroup":"Team Members","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/time-blocks":{"get":{"operationId":"listTimeBlocks","tags":["Time Blocks"],"summary":"List Time Blocks","description":"Lists same-organization Time Blocks — a Team Member's unavailability such as PTO, sick time, or training — ordered by start. Filter by teamMemberId, or by endsAfter to get blocks that have not ended yet. Required scope: time_blocks:read.","x-required-scopes":["time_blocks:read"],"parameters":[{"name":"teamMemberId","in":"query","required":false,"description":"Only Time Blocks for this Team Member.","schema":{"type":"string"}},{"name":"endsAfter","in":"query","required":false,"description":"Only Time Blocks that end after this ISO 8601 date-time.","schema":{"type":"string","format":"date-time"}},{"name":"limit","in":"query","required":false,"description":"Maximum records to return. Defaults to 50 and is capped at 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Opaque record cursor from the previous response meta.nextCursor value.","schema":{"type":"string"}}],"responses":{"200":{"description":"Time Block list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeBlockListEnvelope"}}}},"400":{"description":"endsAfter is not a date-time","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: time_blocks:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.listTimeBlocks","x-llm-guidance":"List Time Blocks. Use an organization API key with time_blocks:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/time-blocks\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/time-blocks`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/time-blocks\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-time-blocks","groupSlug":"time-blocks","navigationGroup":"Time Blocks","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/time-blocks/{id}":{"get":{"operationId":"getTimeBlock","tags":["Time Blocks"],"summary":"Get one Time Block","description":"Returns one same-organization Time Block with its Team Member's Salesforce Service Resource ID. Time Blocks are deleted outright, so 404 means the block no longer exists. Required scope: time_blocks:read.","x-required-scopes":["time_blocks:read"],"responses":{"200":{"description":"Time Block envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeBlockEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: time_blocks:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Time Block identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getTimeBlock","x-llm-guidance":"Get one Time Block. Use an organization API key with time_blocks:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/time-blocks/$SOLAROS_TIME_BLOCK\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/time-blocks/${process.env.SOLAROS_TIME_BLOCK}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/time-blocks/{os.environ['SOLAROS_TIME_BLOCK']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-time-block","groupSlug":"time-blocks","navigationGroup":"Time Blocks","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/activities":{"get":{"operationId":"listActivities","tags":["Activities"],"summary":"List a parent-scoped Activity feed","description":"Lists non-deleted Activities for a supported CRM parent. Required query params: parentType and parentId. Required scope: activities:read.","x-required-scopes":["activities:read"],"parameters":[{"name":"parentType","in":"query","required":true,"description":"Activity parent resource family.","schema":{"type":"string","enum":["customer","property","lead","opportunity","case"]}},{"name":"parentId","in":"query","required":true,"description":"solarOS id of the parent resource.","schema":{"type":"string"}}],"responses":{"200":{"description":"Activity list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: activities:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.listActivities","x-llm-guidance":"List a parent-scoped Activity feed. Use an organization API key with activities:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/activities\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/activities`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/activities\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-activities","groupSlug":"activities","navigationGroup":"Activities","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"post":{"operationId":"createActivity","tags":["Activities"],"summary":"Create a parent-scoped Activity","description":"Creates an Activity for a supported CRM parent, optionally attributed to a same-organization Team Member while preserving API-key audit metadata. Records ActivityLog audit and can create transactional External References such as Salesforce ContentNote ids. Requires Idempotency-Key.","x-required-scopes":["activities:write"],"x-idempotency-key":"required","responses":{"201":{"description":"Activity envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: activities:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for createActivity.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["parentType","parentId","content"],"properties":{"parentType":{"type":"string","enum":["customer","property","lead","opportunity","case"]},"parentId":{"type":"string"},"type":{"type":"string","enum":["NOTE","CALL","EMAIL","MEETING","SMS","TASK"]},"content":{"type":"string"},"authorId":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"visibility":{"type":"string","enum":["INTERNAL","TEAM","CUSTOMER"]},"isPinned":{"type":"boolean"},"metadata":{"type":"object","additionalProperties":true},"externalReferences":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"examples":{"createactivityRequest":{"value":{"parentType":"customer","parentId":"customer_123","type":"NOTE","content":"Customer is comparing storage options.","visibility":"TEAM"}}}}}},"x-tool-name":"orgApi.createActivity","x-llm-guidance":"Create a parent-scoped Activity. Use an organization API key with activities:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/activities\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"parentType\":\"customer\",\"parentId\":\"customer_123\",\"type\":\"NOTE\",\"content\":\"Customer is comparing storage options.\",\"visibility\":\"TEAM\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/activities`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"parentType\": \"customer\",\n    \"parentId\": \"customer_123\",\n    \"type\": \"NOTE\",\n    \"content\": \"Customer is comparing storage options.\",\n    \"visibility\": \"TEAM\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/activities\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"parentType\": \"customer\",\n  \"parentId\": \"customer_123\",\n  \"type\": \"NOTE\",\n  \"content\": \"Customer is comparing storage options.\",\n  \"visibility\": \"TEAM\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-activity","groupSlug":"activities","navigationGroup":"Activities","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/activities/{id}":{"get":{"operationId":"getActivity","tags":["Activities"],"summary":"Get one Activity","description":"Returns one non-deleted Activity inside the organization, including its parent pointer and External References. Required scope: activities:read.","x-required-scopes":["activities:read"],"responses":{"200":{"description":"Activity envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: activities:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Activity identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getActivity","x-llm-guidance":"Get one Activity. Use an organization API key with activities:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/activities/$SOLAROS_ACTIVITY\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/activities/${process.env.SOLAROS_ACTIVITY}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/activities/{os.environ['SOLAROS_ACTIVITY']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-activity","groupSlug":"activities","navigationGroup":"Activities","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"patch":{"operationId":"updateActivity","tags":["Activities"],"summary":"Update an API-authored Activity","description":"Only the API key that created an Activity can update it, including repairing the stored Team Member author. Required scope: activities:write.","x-required-scopes":["activities:write"],"responses":{"200":{"description":"Updated Activity envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Different author","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Activity identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for updateActivity.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"type":{"type":"string","enum":["NOTE","CALL","EMAIL","MEETING","SMS","TASK"]},"content":{"type":"string"},"authorId":{"type":"string"},"visibility":{"type":"string","enum":["INTERNAL","TEAM","CUSTOMER"]},"isPinned":{"type":"boolean"},"metadata":{"type":"object","additionalProperties":true}}},"examples":{"updateactivityRequest":{"value":{"content":"Customer requested a battery backup option.","isPinned":true}}}}}},"x-tool-name":"orgApi.updateActivity","x-llm-guidance":"Update an API-authored Activity. Use an organization API key with activities:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/activities/$SOLAROS_ACTIVITY\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"content\":\"Customer requested a battery backup option.\",\"isPinned\":true}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/activities/${process.env.SOLAROS_ACTIVITY}`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"content\": \"Customer requested a battery backup option.\",\n    \"isPinned\": true\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/activities/{os.environ['SOLAROS_ACTIVITY']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"content\": \"Customer requested a battery backup option.\",\n  \"isPinned\": true\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"update-activity","groupSlug":"activities","navigationGroup":"Activities","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"delete":{"operationId":"deleteActivity","tags":["Activities"],"summary":"Soft-delete an API-authored Activity","description":"Soft-deletes an Activity and hides it from normal feeds. Only the API key that authored it can delete it.","x-required-scopes":["activities:delete"],"responses":{"200":{"description":"Deleted Activity envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Different author","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Activity identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.deleteActivity","x-llm-guidance":"Soft-delete an API-authored Activity. Use an organization API key with activities:delete. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X DELETE \"$SOLAROS_BASE_URL/api/v1/activities/$SOLAROS_ACTIVITY\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/activities/${process.env.SOLAROS_ACTIVITY}`, {\n  method: 'DELETE',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"DELETE\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/activities/{os.environ['SOLAROS_ACTIVITY']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"delete-activity","groupSlug":"activities","navigationGroup":"Activities","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/quote-types":{"get":{"operationId":"listQuoteTypes","tags":["Quotes"],"summary":"List active Company Quote Types","description":"Returns active Company Quote Types, placed Fields, lifecycle defaults, and available Quote Templates needed to create valid draft Quotes. Each placed Field carries showIn (see FieldShowIn) and isPropertyField; its group is the Placement Section, falling back to the deprecated Field Area for Fields no section claims. Required scope: quotes:read.","x-required-scopes":["quotes:read"],"responses":{"200":{"description":"Quote Type catalog envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: quotes:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.listQuoteTypes","x-llm-guidance":"List active Company Quote Types. Use an organization API key with quotes:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/quote-types\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/quote-types`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/quote-types\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-quote-types","groupSlug":"quotes","navigationGroup":"Quotes","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/quote-templates":{"get":{"operationId":"listQuoteTemplates","tags":["Quotes"],"summary":"List active Quote Templates","description":"Returns active Quote Templates, Field defaults, lifecycle overrides, default scope, terms, and line sections. Optional quoteTypeId filter. Required scope: quotes:read.","x-required-scopes":["quotes:read"],"parameters":[{"name":"quoteTypeId","in":"query","required":false,"description":"Filter templates by Quote Type id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Quote Template catalog envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: quotes:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.listQuoteTemplates","x-llm-guidance":"List active Quote Templates. Use an organization API key with quotes:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/quote-templates\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/quote-templates`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/quote-templates\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-quote-templates","groupSlug":"quotes","navigationGroup":"Quotes","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/project-templates":{"get":{"operationId":"listProjectTemplates","tags":["Projects"],"summary":"List enabled Project Templates","description":"Returns Project Templates enabled for the requesting company, including its platform preferences, with stages, items, arranged Project Scope fields and their Placement Sections, and supportsPublicProjectCreate markers. Each Project Scope field carries showIn (see FieldShowIn) and isPropertyField; its fieldArea is deprecated and frozen. Required scope: projects:read.","x-required-scopes":["projects:read"],"responses":{"200":{"description":"Project Template setup envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: projects:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.listProjectTemplates","x-llm-guidance":"List enabled Project Templates. Use an organization API key with projects:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/project-templates\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/project-templates`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/project-templates\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-project-templates","groupSlug":"projects","navigationGroup":"Projects","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/work-types":{"get":{"operationId":"listWorkTypes","tags":["Work Orders"],"summary":"List active Work Types","description":"Returns active platform and organization-scoped Work Types available for project-contained Work Order create. Required scope: work_orders:read.","x-required-scopes":["work_orders:read"],"responses":{"200":{"description":"Work Type catalog envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: work_orders:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.listWorkTypes","x-llm-guidance":"List active Work Types. Use an organization API key with work_orders:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/work-types\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/work-types`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/work-types\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-work-types","groupSlug":"work-orders","navigationGroup":"Work Orders","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/case-categories":{"get":{"operationId":"listCaseCategories","tags":["Cases"],"summary":"List Case Categories","description":"Returns the organization Case Category catalog, including disabled rows so integrations can label historical Cases. Required scope: cases:read.","x-required-scopes":["cases:read"],"responses":{"200":{"description":"Case Category catalog envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: cases:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.listCaseCategories","x-llm-guidance":"List Case Categories. Use an organization API key with cases:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/case-categories\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/case-categories`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/case-categories\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-case-categories","groupSlug":"cases","navigationGroup":"Cases","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/projects":{"get":{"operationId":"listProjects","tags":["Projects"],"summary":"List Projects","description":"Lists narrow Project containers inside the organization and linked Property boundary with customFields, Project Scope, and External References. Each Project carries onHold: true while it has an open hold; holds never change status. Supply externalSystem, externalObject, and externalId together to filter by a canonical External Reference. Project Scope (originalScope, currentScope) carries the sale's money only for a key that also has quotes:content:read, the scope that reads it on the Quote: without it, every field typed Currency and every financing fact (apr, dealerFeePercent, financingTerms, paymentSources, financingScenarioName, loan and financing terms, ppaRatePerKwh, financingEscalatorPercent, pricePerWatt, downPayment, upfrontPayment, monthlyPayment, totalCostWithFinancing) is left out, and projectDetails.pricing and its line items' unitPrice, lineTotal and section subtotal are null. Required scope: projects:read; quotes:content:read for the scope money.","x-required-scopes":["projects:read"],"parameters":[{"name":"limit","in":"query","required":false,"description":"Maximum records to return. Defaults to 50 and is capped at 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Opaque record cursor from the previous response meta.nextCursor value.","schema":{"type":"string"}},{"name":"sortDir","in":"query","required":false,"description":"Sort direction. Defaults to desc.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"status","in":"query","required":false,"description":"Filter by Project status. ON_HOLD is no longer a status and is rejected; use onHold.","schema":{"type":"string","enum":["DRAFT","ACTIVE","COMPLETED","CANCELLED","CLOSED"]}},{"name":"onHold","in":"query","required":false,"description":"true lists Projects with at least one open hold; false lists Projects with none.","schema":{"type":"string","enum":["true","false"]}},{"name":"caseId","in":"query","required":false,"description":"Canonical Case membership. Use null for unlinked Projects.","schema":{"type":"string"}},{"name":"customerId","in":"query","required":false,"description":"Filter by Customer id.","schema":{"type":"string"}},{"name":"propertyId","in":"query","required":false,"description":"Filter by Property id.","schema":{"type":"string"}},{"name":"ownerId","in":"query","required":false,"description":"Filter by owner Team Member id.","schema":{"type":"string"}},{"name":"templateId","in":"query","required":false,"description":"Filter by Project Template id.","schema":{"type":"string"}},{"name":"externalSystem","in":"query","required":false,"description":"External Reference system filter. Supply with externalObject and externalId for exact reconciliation lookup.","schema":{"type":"string"}},{"name":"externalObject","in":"query","required":false,"description":"External Reference object filter. Supply with externalSystem and externalId.","schema":{"type":"string"}},{"name":"externalId","in":"query","required":false,"description":"External Reference id filter. Supply with externalSystem and externalObject.","schema":{"type":"string"}}],"responses":{"200":{"description":"Project list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: projects:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.listProjects","x-llm-guidance":"List Projects. Use an organization API key with projects:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/projects\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/projects`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/projects\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-projects","groupSlug":"projects","navigationGroup":"Projects","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"post":{"operationId":"createProject","tags":["Projects"],"summary":"Create a Project container","description":"Returns canonical caseId. Optional caseId assigns one Case atomically (inherited from quoteId when omitted). Creates a Project for an accessible Customer and linked Property. name, customerId, and propertyId are required. Legacy type is ignored. Creation origin is assigned by the server. Use templateId (not projectTemplateId) for optional Project Template hydration. Arranged Project Scope fields start null unless supplied in projectScope. An answer in projectScope to a Property Field (see isPropertyField) becomes the Property's answer unless the Project is created Completed, Closed or Cancelled, is recorded in its history, and fills that Field on the Property's draft Quotes and open Projects where it is still blank. The created Project is returned with its scope money only for a key that also has quotes:content:read, as GET /v1/projects/{id} returns it. Requires Idempotency-Key and projects:write.","x-required-scopes":["projects:write"],"x-idempotency-key":"required","responses":{"201":{"description":"Created Project envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation, Project Scope, or unsupported template error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: projects:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Customer, Property, Opportunity, or Project Template not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Idempotency or External Reference conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for createProject.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","customerId","propertyId"],"properties":{"name":{"type":"string"},"caseId":{"type":["string","null"]},"type":{"type":"string","deprecated":true,"description":"Ignored compatibility input. Project Type is retired; use templateId for workflow selection."},"customerId":{"type":"string"},"propertyId":{"type":"string"},"opportunityId":{"type":["string","null"]},"quoteId":{"type":["string","null"]},"templateId":{"type":["string","null"]},"status":{"type":"string","enum":["DRAFT","ACTIVE","COMPLETED","CANCELLED","CLOSED"]},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH","URGENT"]},"description":{"type":["string","null"]},"startDate":{"type":["string","null"]},"targetEndDate":{"type":["string","null"]},"ownerId":{"type":["string","null"],"description":"Active or draft same-organization Team Member id. When omitted, the API key default owner for this resource is used. Ownership cannot be changed through generic PATCH endpoints."},"projectScope":{"type":"object","additionalProperties":true},"customFields":{"type":"object","additionalProperties":true,"description":"Field Values keyed by savedIdentity from GET /api/v1/schema."},"externalReferences":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"examples":{"createprojectRequest":{"value":{"customerId":"customer_123","propertyId":"property_123","opportunityId":"opportunity_123","templateId":"project_template_123","name":"Lovelace residential install","status":"ACTIVE","priority":"MEDIUM","projectScope":{"systemSizeKw":8.4,"storageKwh":13.5}}}}}}},"x-tool-name":"orgApi.createProject","x-llm-guidance":"Create a Project container. Use an organization API key with projects:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/projects\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"customerId\":\"customer_123\",\"propertyId\":\"property_123\",\"opportunityId\":\"opportunity_123\",\"templateId\":\"project_template_123\",\"name\":\"Lovelace residential install\",\"status\":\"ACTIVE\",\"priority\":\"MEDIUM\",\"projectScope\":{\"systemSizeKw\":8.4,\"storageKwh\":13.5}}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/projects`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"customerId\": \"customer_123\",\n    \"propertyId\": \"property_123\",\n    \"opportunityId\": \"opportunity_123\",\n    \"templateId\": \"project_template_123\",\n    \"name\": \"Lovelace residential install\",\n    \"status\": \"ACTIVE\",\n    \"priority\": \"MEDIUM\",\n    \"projectScope\": {\n      \"systemSizeKw\": 8.4,\n      \"storageKwh\": 13.5\n    }\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/projects\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"customerId\": \"customer_123\",\n  \"propertyId\": \"property_123\",\n  \"opportunityId\": \"opportunity_123\",\n  \"templateId\": \"project_template_123\",\n  \"name\": \"Lovelace residential install\",\n  \"status\": \"ACTIVE\",\n  \"priority\": \"MEDIUM\",\n  \"projectScope\": {\n    \"systemSizeKw\": 8.4,\n    \"storageKwh\": 13.5\n  }\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-project","groupSlug":"projects","navigationGroup":"Projects","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/projects/{id}":{"get":{"operationId":"getProject","tags":["Projects"],"summary":"Get one Project (including canonical caseId)","description":"Returns one Project inside the organization and linked Property boundary, with onHold: true while it has an open hold. Project Scope (originalScope, currentScope) carries the sale's money only for a key that also has quotes:content:read, the scope that reads it on the Quote: without it, every field typed Currency and every financing fact (apr, dealerFeePercent, financingTerms, paymentSources, financingScenarioName, loan and financing terms, ppaRatePerKwh, financingEscalatorPercent, pricePerWatt, downPayment, upfrontPayment, monthlyPayment, totalCostWithFinancing) is left out, and projectDetails.pricing and its line items' unitPrice, lineTotal and section subtotal are null. Cross-tenant or inaccessible records return 404. Required scope: projects:read; quotes:content:read for the scope money.","x-required-scopes":["projects:read"],"responses":{"200":{"description":"Project envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: projects:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Project identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getProject","x-llm-guidance":"Get one Project (including canonical caseId). Use an organization API key with projects:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/projects/$SOLAROS_PROJECT\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/projects/${process.env.SOLAROS_PROJECT}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/projects/{os.environ['SOLAROS_PROJECT']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-project","groupSlug":"projects","navigationGroup":"Projects","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"patch":{"operationId":"updateProject","tags":["Projects"],"summary":"Update a Project container","description":"Updates narrow Project metadata and customFields. ownerId is create-only and is rejected on PATCH because Organization API v1 does not expose the staff reassignment action. status ON_HOLD is rejected: holds are placed in solarOS and never change status, and onHold reports them. Moving a project with an open hold to COMPLETED, CLOSED or CANCELLED returns 409 CONFLICT: resolve its holds in solarOS first. No-op PATCH returns changed=false and does not emit audit/domain events. The Project is returned with its scope money only for a key that also has quotes:content:read, as GET /v1/projects/{id} returns it.","x-required-scopes":["projects:write"],"responses":{"200":{"description":"Updated Project envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: projects:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Conflict, such as finishing a project that has an open hold","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Project identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for updateProject.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"caseId":{"type":["string","null"]},"expectedCaseId":{"type":["string","null"],"description":"Supply the current Case ID when unlinking; stale or conflicting assignments return 409."},"type":{"type":"string","deprecated":true,"description":"Ignored compatibility input. Project Type is retired; use templateId for workflow selection."},"status":{"type":"string","enum":["DRAFT","ACTIVE","COMPLETED","CANCELLED","CLOSED"]},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH","URGENT"]},"description":{"type":["string","null"]},"targetEndDate":{"type":["string","null"]},"customFields":{"type":"object","additionalProperties":true,"description":"Field Values keyed by savedIdentity from GET /api/v1/schema."}}},"examples":{"updateprojectRequest":{"value":{"status":"ACTIVE","priority":"HIGH","customFields":{"permitJurisdiction":"San Francisco"}}}}}}},"x-tool-name":"orgApi.updateProject","x-llm-guidance":"Update a Project container. Use an organization API key with projects:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/projects/$SOLAROS_PROJECT\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"status\":\"ACTIVE\",\"priority\":\"HIGH\",\"customFields\":{\"permitJurisdiction\":\"San Francisco\"}}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/projects/${process.env.SOLAROS_PROJECT}`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"status\": \"ACTIVE\",\n    \"priority\": \"HIGH\",\n    \"customFields\": {\n      \"permitJurisdiction\": \"San Francisco\"\n    }\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/projects/{os.environ['SOLAROS_PROJECT']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"status\": \"ACTIVE\",\n  \"priority\": \"HIGH\",\n  \"customFields\": {\n    \"permitJurisdiction\": \"San Francisco\"\n  }\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"update-project","groupSlug":"projects","navigationGroup":"Projects","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/projects/{id}/system":{"get":{"operationId":"getProjectSoldSystem","tags":["Projects"],"summary":"Get a Project's Sold System","description":"Returns the solar system the Project was sold with: the quote's Solar System Record (version 1), frozen when the accepted quote handed off to the Project and never changed by later quote edits. A Project made with no quote has one when its solar facts were entered at New Project: source.quoteId and source.quoteNumber are null, and it holds what was entered and the price and payments it was made with, with storage, production, usage, utility and savings null unless entered. A Project sold before Sold Systems were kept gets one from a one-time backfill, and its source.backfilledFrom says what it was rebuilt from: QUOTE (the accepted quote's design) or PROJECT_SCOPE (the Project's copy of the sale, without price, usage, savings or payments). It holds the scope (PV, PV_STORAGE or STORAGE_ONLY), totals, arrays, inverters, batteries in units, storage and backup, production, usage, utility and rates, savings, price, financing, payment schedule, site, printable display strings (display.summarySentence names the system in one sentence), media (media.designImageKey is the stored design picture's reference, not a URL) and, once the agreement is signed, agreement.contractId. The sale's money needs quotes:content:read as well, the scope that reads it on the Quote: without it, price, financing (with its dealerFeePercent) and payments are null, so are display.ppaRate, display.paymentSources and display.financingTerms, and moneyWithheld is true; with it, moneyWithheld is false. Money is in dollars, energy in kWh, power in kW, and monthly series run January to December. Returns 404 NOT_FOUND when the Project is outside the organization's Property access or has no Sold System. Required scope: projects:read; quotes:content:read for price, financing and payments.","x-required-scopes":["projects:read"],"responses":{"200":{"description":"Sold System envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"required":["data","meta"],"properties":{"data":{"type":"object","properties":{"version":{"type":"number","const":1},"capturedAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z))$"},"source":{"type":"object","properties":{"builder":{"type":"string","enum":["SOLAROS","AURORA","OPENSOLAR"]},"quoteId":{"anyOf":[{"type":"string"},{"type":"null"}]},"quoteNumber":{"anyOf":[{"type":"string"},{"type":"null"}]},"designFingerprint":{"anyOf":[{"type":"string"},{"type":"null"}]},"import":{"anyOf":[{"type":"object","properties":{"provider":{"type":"string","enum":["AURORA","OPENSOLAR"]},"projectId":{"type":"string"},"designId":{"type":"string"},"designName":{"type":"string"},"revision":{"type":"string"},"importedAt":{"type":"string"},"parts":{"type":"array","items":{"type":"string","enum":["design","usage","price","financing"]}},"detachedParts":{"type":"array","items":{"type":"string","enum":["design","usage","price","financing"]}}},"required":["provider","projectId","designId","designName","revision","importedAt","parts","detachedParts"],"additionalProperties":false},{"type":"null"}]},"backfilledFrom":{"type":"string","enum":["QUOTE","PROJECT_SCOPE"]}},"required":["builder","quoteId","quoteNumber","designFingerprint","import"],"additionalProperties":false},"scope":{"type":"string","enum":["PV","PV_STORAGE","STORAGE_ONLY"]},"totals":{"type":"object","properties":{"dcKw":{"anyOf":[{"type":"number"},{"type":"null"}]},"inverterAcKw":{"anyOf":[{"type":"number"},{"type":"null"}]},"panelCount":{"type":"number"},"arrayCount":{"type":"number"},"inverterUnits":{"type":"number"},"batteryUnits":{"type":"number"},"primaryBatteryUnits":{"type":"number"},"secondaryBatteryUnits":{"type":"number"},"usableKwh":{"anyOf":[{"type":"number"},{"type":"null"}]},"batteryPowerKw":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["dcKw","inverterAcKw","panelCount","arrayCount","inverterUnits","batteryUnits","primaryBatteryUnits","secondaryBatteryUnits","usableKwh","batteryPowerKw"],"additionalProperties":false},"arrays":{"type":"array","items":{"type":"object","properties":{"name":{"anyOf":[{"type":"string"},{"type":"null"}]},"panelCount":{"type":"number"},"module":{"anyOf":[{"type":"object","properties":{"productId":{"anyOf":[{"type":"string"},{"type":"null"}]},"masterProductId":{"anyOf":[{"type":"string"},{"type":"null"}]},"manufacturer":{"anyOf":[{"type":"string"},{"type":"null"}]},"model":{"anyOf":[{"type":"string"},{"type":"null"}]},"displayName":{"type":"string"}},"required":["productId","masterProductId","manufacturer","model","displayName"],"additionalProperties":false},{"type":"null"}]},"panelWatts":{"type":"number"},"dcKw":{"type":"number"},"azimuth":{"anyOf":[{"type":"number"},{"type":"null"}]},"tilt":{"anyOf":[{"type":"number"},{"type":"null"}]},"mount":{"type":"string","enum":["ROOF","GROUND"]},"shadingFactor":{"anyOf":[{"type":"number"},{"type":"null"}]},"soilingFactor":{"anyOf":[{"type":"number"},{"type":"null"}]},"snowLossFactor":{"anyOf":[{"type":"number"},{"type":"null"}]},"annualKwh":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["name","panelCount","module","panelWatts","dcKw","azimuth","tilt","mount","shadingFactor","soilingFactor","snowLossFactor","annualKwh"],"additionalProperties":false}},"inverters":{"type":"array","items":{"type":"object","properties":{"kind":{"type":"string","enum":["MICRO","STRING","HYBRID","BUILT_IN","OTHER"]},"equipment":{"type":"object","properties":{"productId":{"anyOf":[{"type":"string"},{"type":"null"}]},"masterProductId":{"anyOf":[{"type":"string"},{"type":"null"}]},"manufacturer":{"anyOf":[{"type":"string"},{"type":"null"}]},"model":{"anyOf":[{"type":"string"},{"type":"null"}]},"displayName":{"type":"string"}},"required":["productId","masterProductId","manufacturer","model","displayName"],"additionalProperties":false},"quantity":{"type":"number"},"acKw":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["kind","equipment","quantity","acKw"],"additionalProperties":false}},"batteries":{"type":"array","items":{"type":"object","properties":{"role":{"type":"string","enum":["PRIMARY","EXPANSION"]},"equipment":{"type":"object","properties":{"productId":{"anyOf":[{"type":"string"},{"type":"null"}]},"masterProductId":{"anyOf":[{"type":"string"},{"type":"null"}]},"manufacturer":{"anyOf":[{"type":"string"},{"type":"null"}]},"model":{"anyOf":[{"type":"string"},{"type":"null"}]},"displayName":{"type":"string"}},"required":["productId","masterProductId","manufacturer","model","displayName"],"additionalProperties":false},"quantity":{"type":"number"},"usableKwhEach":{"anyOf":[{"type":"number"},{"type":"null"}]},"powerKwEach":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["role","equipment","quantity","usableKwhEach","powerKwEach"],"additionalProperties":false}},"storage":{"anyOf":[{"type":"object","properties":{"operatingMode":{"type":"string","enum":["PRICE_BASED","SELF_POWERED","BACKUP_ONLY","CUSTOM"]},"backupType":{"anyOf":[{"type":"string","enum":["WHOLE_HOME_METER_ADAPTER","WHOLE_HOME_GATEWAY","ESSENTIAL_LOADS_PANEL","NO_BACKUP","EXISTING_BACKUP"]},{"type":"null"}]},"reservePercent":{"type":"number"},"essentialLoadKw":{"anyOf":[{"type":"number"},{"type":"null"}]},"backupHours":{"type":"object","properties":{"essential":{"anyOf":[{"type":"number"},{"type":"null"}]},"wholeHome":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["essential","wholeHome"],"additionalProperties":false},"gridChargingAllowed":{"type":"boolean"}},"required":["operatingMode","backupType","reservePercent","essentialLoadKw","backupHours","gridChargingAllowed"],"additionalProperties":false},{"type":"null"}]},"production":{"anyOf":[{"type":"object","properties":{"annualKwh":{"anyOf":[{"type":"number"},{"type":"null"}]},"monthlyKwh":{"anyOf":[{"minItems":12,"maxItems":12,"type":"array","items":{"type":"number"}},{"type":"null"}]},"source":{"anyOf":[{"type":"string","enum":["PVWATTS","LOOKUP","MANUAL","IMPORTED"]},{"type":"null"}]},"importedFrom":{"anyOf":[{"type":"string","enum":["AURORA","OPENSOLAR"]},{"type":"null"}]},"lossesPercent":{"anyOf":[{"type":"number"},{"type":"null"}]},"offsetPercent":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["annualKwh","monthlyKwh","source","importedFrom","lossesPercent","offsetPercent"],"additionalProperties":false},{"type":"null"}]},"usage":{"anyOf":[{"type":"object","properties":{"annualKwh":{"anyOf":[{"type":"number"},{"type":"null"}]},"monthlyKwh":{"anyOf":[{"minItems":12,"maxItems":12,"type":"array","items":{"type":"number"}},{"type":"null"}]},"basis":{"anyOf":[{"type":"string","enum":["TWELVE_MONTHS","PARTIAL","ESTIMATED"]},{"type":"null"}]},"basisNote":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["annualKwh","monthlyKwh","basis","basisNote"],"additionalProperties":false},{"type":"null"}]},"utility":{"anyOf":[{"type":"object","properties":{"utilityName":{"anyOf":[{"type":"string"},{"type":"null"}]},"ratePlanBefore":{"anyOf":[{"type":"object","properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}]},"code":{"anyOf":[{"type":"string"},{"type":"null"}]},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false},{"type":"null"}]},"ratePlanAfter":{"anyOf":[{"type":"object","properties":{"id":{"anyOf":[{"type":"string"},{"type":"null"}]},"code":{"anyOf":[{"type":"string"},{"type":"null"}]},"name":{"type":"string"}},"required":["id","code","name"],"additionalProperties":false},{"type":"null"}]},"generationSupplier":{"anyOf":[{"type":"object","properties":{"name":{"type":"string"},"product":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["name","product"],"additionalProperties":false},{"type":"null"}]},"pciaVintage":{"anyOf":[{"type":"number"},{"type":"null"}]},"baselineTerritory":{"anyOf":[{"type":"string"},{"type":"null"}]},"interconnectionYear":{"anyOf":[{"type":"number"},{"type":"null"}]},"interconnectionYearConfirmed":{"type":"boolean"}},"required":["utilityName","ratePlanBefore","ratePlanAfter","generationSupplier","pciaVintage","baselineTerritory","interconnectionYear","interconnectionYearConfirmed"],"additionalProperties":false},{"type":"null"}]},"savings":{"anyOf":[{"type":"object","properties":{"billBeforeAnnual":{"anyOf":[{"type":"number"},{"type":"null"}]},"billAfterAnnual":{"anyOf":[{"type":"number"},{"type":"null"}]},"billsBeforeMonthly":{"anyOf":[{"minItems":12,"maxItems":12,"type":"array","items":{"type":"number"}},{"type":"null"}]},"billsAfterMonthly":{"anyOf":[{"minItems":12,"maxItems":12,"type":"array","items":{"type":"number"}},{"type":"null"}]},"firstYearSavings":{"anyOf":[{"type":"number"},{"type":"null"}]},"firstYearByMode":{"anyOf":[{"type":"object","properties":{"priceBased":{"anyOf":[{"type":"number"},{"type":"null"}]},"selfPowered":{"anyOf":[{"type":"number"},{"type":"null"}]},"backupFirst":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["priceBased","selfPowered","backupFirst"],"additionalProperties":false},{"type":"null"}]},"lifetimeSavings":{"anyOf":[{"type":"number"},{"type":"null"}]},"paybackYears":{"anyOf":[{"type":"number"},{"type":"null"}]},"calculator":{"type":"string"}},"required":["billBeforeAnnual","billAfterAnnual","billsBeforeMonthly","billsAfterMonthly","firstYearSavings","firstYearByMode","lifetimeSavings","paybackYears","calculator"],"additionalProperties":false},{"type":"null"}]},"price":{"anyOf":[{"type":"object","properties":{"contractPrice":{"anyOf":[{"type":"number"},{"type":"null"}]},"pricePerWatt":{"anyOf":[{"type":"number"},{"type":"null"}]},"basePrice":{"anyOf":[{"type":"number"},{"type":"null"}]},"adders":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"amount":{"type":"number"},"customerVisible":{"type":"boolean"},"additionalScope":{"type":"boolean"}},"required":["name","amount","customerVisible","additionalScope"],"additionalProperties":false}},"discounts":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"amount":{"type":"number"}},"required":["name","amount"],"additionalProperties":false}},"incentives":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"amount":{"type":"number"},"customerFacing":{"type":"boolean"}},"required":["name","amount","customerFacing"],"additionalProperties":false}},"adderTotal":{"type":"number"},"discountTotal":{"type":"number"},"incentiveTotal":{"type":"number"},"taxAmount":{"anyOf":[{"type":"number"},{"type":"null"}]},"netCost":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["contractPrice","pricePerWatt","basePrice","adders","discounts","incentives","adderTotal","discountTotal","incentiveTotal","taxAmount","netCost"],"additionalProperties":false},{"type":"null"}]},"financing":{"anyOf":[{"type":"object","properties":{"kind":{"type":"string","enum":["CASH","LOAN","LEASE","PPA","PREPAID_TPO"]},"planName":{"type":"string"},"lender":{"anyOf":[{"type":"string"},{"type":"null"}]},"termMonths":{"anyOf":[{"type":"number"},{"type":"null"}]},"termYears":{"anyOf":[{"type":"number"},{"type":"null"}]},"termMonthsRemainder":{"anyOf":[{"type":"number"},{"type":"null"}]},"aprPercent":{"anyOf":[{"type":"number"},{"type":"null"}]},"dealerFeePercent":{"anyOf":[{"type":"number"},{"type":"null"}]},"downPayment":{"anyOf":[{"type":"number"},{"type":"null"}]},"amountFinanced":{"anyOf":[{"type":"number"},{"type":"null"}]},"monthlyPayment":{"anyOf":[{"type":"number"},{"type":"null"}]},"totalOfPayments":{"anyOf":[{"type":"number"},{"type":"null"}]},"escalatorPercent":{"anyOf":[{"type":"number"},{"type":"null"}]},"ppaRatePerKwh":{"anyOf":[{"type":"number"},{"type":"null"}]},"upfrontPayment":{"anyOf":[{"type":"number"},{"type":"null"}]},"totalCostWithFinancing":{"anyOf":[{"type":"number"},{"type":"null"}]},"isPurchase":{"type":"boolean"},"isThirdPartyOwned":{"type":"boolean"},"isContractorLoan":{"type":"boolean"},"canTransferToNewOwner":{"anyOf":[{"type":"boolean"},{"type":"null"}]}},"required":["kind","planName","lender","termMonths","termYears","termMonthsRemainder","aprPercent","dealerFeePercent","downPayment","amountFinanced","monthlyPayment","totalOfPayments","escalatorPercent","ppaRatePerKwh","upfrontPayment","totalCostWithFinancing","isPurchase","isThirdPartyOwned","isContractorLoan","canTransferToNewOwner"],"additionalProperties":false},{"type":"null"}]},"payments":{"anyOf":[{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"amount":{"type":"number"},"percent":{"anyOf":[{"type":"number"},{"type":"null"}]},"dueUpon":{"anyOf":[{"type":"string"},{"type":"null"}]},"payer":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["name","amount","percent","dueUpon","payer"],"additionalProperties":false}},{"type":"null"}]},"site":{"type":"object","properties":{"roofType":{"anyOf":[{"type":"string"},{"type":"null"}]},"roofAgeYears":{"anyOf":[{"type":"number"},{"type":"null"}]},"siteNotes":{"anyOf":[{"type":"string"},{"type":"null"}]},"lat":{"anyOf":[{"type":"number"},{"type":"null"}]},"lng":{"anyOf":[{"type":"number"},{"type":"null"}]}},"required":["roofType","roofAgeYears","siteNotes","lat","lng"],"additionalProperties":false},"display":{"type":"object","properties":{"moduleModel":{"anyOf":[{"type":"string"},{"type":"null"}]},"moduleWattage":{"anyOf":[{"type":"string"},{"type":"null"}]},"inverterModel":{"anyOf":[{"type":"string"},{"type":"null"}]},"inverterType":{"anyOf":[{"type":"string"},{"type":"null"}]},"primaryBatteryModel":{"anyOf":[{"type":"string"},{"type":"null"}]},"secondaryBatteryModel":{"anyOf":[{"type":"string"},{"type":"null"}]},"backupType":{"anyOf":[{"type":"string"},{"type":"null"}]},"ratePlanBefore":{"anyOf":[{"type":"string"},{"type":"null"}]},"ratePlanAfter":{"anyOf":[{"type":"string"},{"type":"null"}]},"generationSupplier":{"anyOf":[{"type":"string"},{"type":"null"}]},"interconnectionYear":{"anyOf":[{"type":"string"},{"type":"null"}]},"ppaRate":{"anyOf":[{"type":"string"},{"type":"null"}]},"paymentSources":{"anyOf":[{"type":"string"},{"type":"null"}]},"financingTerms":{"anyOf":[{"type":"string"},{"type":"null"}]},"additionalScope":{"anyOf":[{"type":"string"},{"type":"null"}]},"summarySentence":{"type":"string"}},"required":["moduleModel","moduleWattage","inverterModel","inverterType","primaryBatteryModel","secondaryBatteryModel","backupType","ratePlanBefore","ratePlanAfter","generationSupplier","interconnectionYear","ppaRate","paymentSources","financingTerms","additionalScope","summarySentence"],"additionalProperties":false},"media":{"type":"object","properties":{"designImageKey":{"anyOf":[{"type":"string"},{"type":"null"}]},"designImageFingerprint":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["designImageKey","designImageFingerprint"],"additionalProperties":false},"agreement":{"type":"object","properties":{"contractId":{"type":"string"},"templateVersionId":{"anyOf":[{"type":"string"},{"type":"null"}]}},"required":["contractId","templateVersionId"],"additionalProperties":false},"moneyWithheld":{"description":"True when the API key lacks quotes:content:read: price, financing and payments are then null, and so are display.ppaRate, display.paymentSources and display.financingTerms.","type":"boolean"}},"required":["version","capturedAt","source","scope","totals","arrays","inverters","batteries","storage","production","usage","utility","savings","price","financing","payments","site","display","media","moneyWithheld"],"additionalProperties":false},"meta":{"$ref":"#/components/schemas/OrgApiMeta"}}}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: projects:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found, or the Project has no Sold System","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Project identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getProjectSoldSystem","x-llm-guidance":"Get a Project's Sold System. Use an organization API key with projects:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/projects/$SOLAROS_PROJECT/system\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/projects/${process.env.SOLAROS_PROJECT}/system`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/projects/{os.environ['SOLAROS_PROJECT']}/system\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-project-sold-system","groupSlug":"projects","navigationGroup":"Projects","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/cases":{"get":{"operationId":"listCases","tags":["Cases"],"summary":"List Cases","description":"Lists first-class service Cases inside the organization boundary. Filters combine, and query parameters not listed here are ignored. Supply externalSystem, externalObject, and externalId together to filter by a canonical External Reference. With sortBy=updatedAt, each page continues from where the last one ended even if a Case on it is edited meanwhile. To sync, use sortDir=asc: a Case edited during a pass appears again later in it. With sortDir=desc, a Case edited during a pass moves ahead of the pages already read, so that pass skips it and the next one lists it first. Required scope: cases:read.","x-required-scopes":["cases:read"],"parameters":[{"name":"limit","in":"query","required":false,"description":"Maximum records to return. Defaults to 50 and is capped at 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Opaque record cursor from the previous response meta.nextCursor value.","schema":{"type":"string"}},{"name":"sortBy","in":"query","required":false,"description":"Case sort field. Defaults to openedAt; an empty value also uses openedAt.","schema":{"type":"string","enum":["openedAt","updatedAt"],"default":"openedAt"}},{"name":"sortDir","in":"query","required":false,"description":"Sort direction. Defaults to desc.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"status","in":"query","required":false,"description":"Filter by Case status. Separate several statuses with commas, for example OPEN,TRIAGING, or repeat the parameter, for example status=OPEN&status=TRIAGING, to match any of them; a single status works as before. Every value must be a status: an unknown one, repeated or not, returns 400. Changed 2026-10-15: a repeated status parameter used to be read for its first value only, so later values, unknown or not, were ignored. To keep a request working, send only Case statuses. CLOSED is the sole terminal status; legacy RESOLVED filters are treated as CLOSED.","style":"form","explode":false,"schema":{"type":"array","items":{"type":"string","enum":["OPEN","TRIAGING","IN_PROGRESS","AWAITING_CUSTOMER","AWAITING_VENDOR","AWAITING_WORK","RESOLVED","CLOSED"]}}},{"name":"customerId","in":"query","required":false,"description":"Filter by Customer id.","schema":{"type":"string"}},{"name":"propertyId","in":"query","required":false,"description":"Filter by Property id.","schema":{"type":"string"}},{"name":"projectId","in":"query","required":false,"description":"Filter by a Project the Case has had, including earlier work cycles.","schema":{"type":"string"}},{"name":"ownerId","in":"query","required":false,"description":"Filter by owner Team Member id. Use unassigned for Cases without an owner.","schema":{"type":"string"}},{"name":"caseNumber","in":"query","required":false,"description":"Filter by exact Case number, such as CASE-00042. A number from before five-digit Record Numbers (CASE-2026-000042) finds the same case.","schema":{"type":"string"}},{"name":"search","in":"query","required":false,"description":"Case-insensitive text matched against the Case number, subject and description.","schema":{"type":"string"}},{"name":"updatedSince","in":"query","required":false,"description":"Return Cases updated at or after this ISO 8601 date-time, including a saved Case Field and an External Record Link added or removed. Include Z or a UTC offset, for example 2026-10-01T00:00:00Z. Send the + of an offset as %2B, for example 2026-10-01T00:00:00%2B02:00: an unencoded + reads as a space.","schema":{"type":"string","format":"date-time"}},{"name":"externalSystem","in":"query","required":false,"description":"External Reference system filter. Supply with externalObject and externalId for exact reconciliation lookup.","schema":{"type":"string"}},{"name":"externalObject","in":"query","required":false,"description":"External Reference object filter. Supply with externalSystem and externalId.","schema":{"type":"string"}},{"name":"externalId","in":"query","required":false,"description":"External Reference id filter. Supply with externalSystem and externalObject.","schema":{"type":"string"}}],"responses":{"200":{"description":"Case list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseListEnvelope"}}}},"400":{"description":"UNSUPPORTED_SORT: a sortBy other than openedAt or updatedAt, or a sortDir other than asc or desc. VALIDATION_FAILED: a status that is not a Case status; an updatedSince that is not an ISO 8601 date-time with Z or a UTC offset; or externalSystem, externalObject and externalId not sent together, or one of them empty or too long.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: cases:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.listCases","x-llm-guidance":"List Cases. Use an organization API key with cases:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/cases\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/cases`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/cases\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-cases","groupSlug":"cases","navigationGroup":"Cases","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"post":{"operationId":"createCase","tags":["Cases"],"summary":"Create a Case","description":"Creates a first-class service Case for an accessible Customer and linked Property. Requires Idempotency-Key. External References are created transactionally and conflicts return 409. Required scope: cases:write.","x-required-scopes":["cases:write"],"x-idempotency-key":"required","responses":{"201":{"description":"Created Case envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseEnvelope"}}}},"400":{"description":"Validation, owner, or idempotency error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: cases:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Customer, Property, System, Project, or Service Request not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Idempotency or External Reference conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for createCase.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["customerId","propertyId","subject","description","origin","category"],"properties":{"customerId":{"type":"string"},"propertyId":{"type":"string"},"systemId":{"type":["string","null"]},"projectId":{"type":["string","null"],"deprecated":true,"description":"Current project compatibility pointer. Changing or clearing it preserves prior Project memberships. Use Project.caseId to link/unlink membership."},"subject":{"type":"string"},"description":{"type":"string"},"origin":{"type":"string","enum":["PHONE","EMAIL","PORTAL","MONITORING_ALERT","IN_PERSON"]},"severity":{"type":"string","enum":["LOW","MEDIUM","HIGH","URGENT"],"default":"MEDIUM"},"category":{"type":"string","description":"Case Category key. Platform keys: HARDWARE_DEFECT, WORKMANSHIP, MONITORING, BILLING, OTHER. Organizations may add their own; list them with GET /case-categories."},"status":{"type":"string","enum":["OPEN","TRIAGING","IN_PROGRESS","AWAITING_CUSTOMER","AWAITING_VENDOR","AWAITING_WORK","RESOLVED","CLOSED"],"default":"OPEN","description":"CLOSED is the sole terminal status. Legacy RESOLVED input is accepted as CLOSED."},"ownerId":{"type":["string","null"],"description":"Active or draft same-organization Team Member id. When omitted, the API key default owner for this resource is used. Ownership cannot be changed through generic PATCH endpoints."},"sourceServiceRequestId":{"type":"string"},"slaResponseDueAt":{"type":"string","format":"date-time"},"externalReferences":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"examples":{"createcaseRequest":{"value":{"customerId":"customer_123","propertyId":"property_123","subject":"Inverter is offline","description":"Monitoring data shows that the inverter stopped reporting this morning.","origin":"MONITORING_ALERT","severity":"MEDIUM","category":"MONITORING"}}}}}},"x-tool-name":"orgApi.createCase","x-llm-guidance":"Create a Case. Use an organization API key with cases:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/cases\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"customerId\":\"customer_123\",\"propertyId\":\"property_123\",\"subject\":\"Inverter is offline\",\"description\":\"Monitoring data shows that the inverter stopped reporting this morning.\",\"origin\":\"MONITORING_ALERT\",\"severity\":\"MEDIUM\",\"category\":\"MONITORING\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/cases`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"customerId\": \"customer_123\",\n    \"propertyId\": \"property_123\",\n    \"subject\": \"Inverter is offline\",\n    \"description\": \"Monitoring data shows that the inverter stopped reporting this morning.\",\n    \"origin\": \"MONITORING_ALERT\",\n    \"severity\": \"MEDIUM\",\n    \"category\": \"MONITORING\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/cases\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"customerId\": \"customer_123\",\n  \"propertyId\": \"property_123\",\n  \"subject\": \"Inverter is offline\",\n  \"description\": \"Monitoring data shows that the inverter stopped reporting this morning.\",\n  \"origin\": \"MONITORING_ALERT\",\n  \"severity\": \"MEDIUM\",\n  \"category\": \"MONITORING\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-case","groupSlug":"cases","navigationGroup":"Cases","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/cases/{id}":{"get":{"operationId":"getCase","tags":["Cases"],"summary":"Get one Case","description":"Returns one first-class Case inside the organization boundary. Cross-tenant records return 404.","x-required-scopes":["cases:read"],"responses":{"200":{"description":"Case envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: cases:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Case identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getCase","x-llm-guidance":"Get one Case. Use an organization API key with cases:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/cases/$SOLAROS_CASE\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/cases/${process.env.SOLAROS_CASE}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/cases/{os.environ['SOLAROS_CASE']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-case","groupSlug":"cases","navigationGroup":"Cases","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"patch":{"operationId":"updateCase","tags":["Cases"],"summary":"Update editable Case metadata","description":"Updates editable Case metadata, status, Project link, and first-response marker. customerId, propertyId, systemId, ownerId, and the removed assignedToId field are not writable on PATCH.","x-required-scopes":["cases:write"],"responses":{"200":{"description":"Updated Case envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseEnvelope"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: cases:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Case identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for updateCase.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"subject":{"type":"string"},"description":{"type":"string"},"origin":{"type":"string","enum":["PHONE","EMAIL","PORTAL","MONITORING_ALERT","IN_PERSON"]},"severity":{"type":"string","enum":["LOW","MEDIUM","HIGH","URGENT"]},"category":{"type":"string","description":"Case Category key. Platform keys: HARDWARE_DEFECT, WORKMANSHIP, MONITORING, BILLING, OTHER. Organizations may add their own; list them with GET /case-categories."},"status":{"type":"string","enum":["OPEN","TRIAGING","IN_PROGRESS","AWAITING_CUSTOMER","AWAITING_VENDOR","AWAITING_WORK","RESOLVED","CLOSED"],"description":"CLOSED is the sole terminal status. Legacy RESOLVED input is accepted as CLOSED."},"projectId":{"type":["string","null"],"deprecated":true,"description":"Current project compatibility pointer. Changing or clearing it preserves prior Project memberships. Use Project.caseId to link/unlink membership."},"firstResponseAt":{"type":["string","null"],"format":"date-time"}}},"examples":{"updatecaseRequest":{"value":{"status":"IN_PROGRESS","firstResponseAt":"2026-08-12T18:00:00Z"}}}}}},"x-tool-name":"orgApi.updateCase","x-llm-guidance":"Update editable Case metadata. Use an organization API key with cases:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/cases/$SOLAROS_CASE\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"status\":\"IN_PROGRESS\",\"firstResponseAt\":\"2026-08-12T18:00:00Z\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/cases/${process.env.SOLAROS_CASE}`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"status\": \"IN_PROGRESS\",\n    \"firstResponseAt\": \"2026-08-12T18:00:00Z\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/cases/{os.environ['SOLAROS_CASE']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"status\": \"IN_PROGRESS\",\n  \"firstResponseAt\": \"2026-08-12T18:00:00Z\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"update-case","groupSlug":"cases","navigationGroup":"Cases","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/cases/{id}/fields":{"patch":{"operationId":"updateCaseFields","tags":["Cases"],"summary":"Save Case Field Values","description":"Writes registered Field Values by key. Set preserveExisting to fill only unanswered Fields, preserving zero, false, and existing answers even during concurrent edits. Omitted keys remain unchanged. With preserveExisting false (the default), null clears an answer. Saves follow normal Case inheritance into unanswered draft Quote and Project Fields. GET /cases/{id} returns the values in customFields.","x-required-scopes":["cases:write"],"responses":{"200":{"description":"Saved Case Fields and the keys updated by this request","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"customFields":{"type":"object","additionalProperties":true},"updatedFields":{"type":"array","items":{"type":"string"}}}}}}}}},"400":{"description":"Malformed payload or unknown, unavailable, or invalid Field Value","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: cases:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Case not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Case identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for updateCaseFields.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["values"],"properties":{"values":{"type":"object","additionalProperties":true,"description":"Field Values keyed by savedIdentity from GET /api/v1/schema."},"preserveExisting":{"type":"boolean","default":false}}},"examples":{"updatecasefieldsRequest":{"value":{"values":{"storyCount":2,"roofPitch":"4_12","panelCount":18},"preserveExisting":true}}}}}},"x-tool-name":"orgApi.updateCaseFields","x-llm-guidance":"Save Case Field Values. Use an organization API key with cases:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/cases/$SOLAROS_CASE/fields\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"values\":{\"storyCount\":2,\"roofPitch\":\"4_12\",\"panelCount\":18},\"preserveExisting\":true}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/cases/${process.env.SOLAROS_CASE}/fields`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"values\": {\n      \"storyCount\": 2,\n      \"roofPitch\": \"4_12\",\n      \"panelCount\": 18\n    },\n    \"preserveExisting\": true\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/cases/{os.environ['SOLAROS_CASE']}/fields\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"values\": {\n    \"storyCount\": 2,\n    \"roofPitch\": \"4_12\",\n    \"panelCount\": 18\n  },\n  \"preserveExisting\": true\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"update-case-fields","groupSlug":"cases","navigationGroup":"Cases","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/cases/{id}/external-record-links":{"get":{"operationId":"listCaseExternalRecordLinks","tags":["Cases"],"summary":"List External Record Links on a Case","description":"Returns navigable context links from a Case to related records in external systems. External Record Links are not identity-bearing External References.","x-required-scopes":["cases:read"],"responses":{"200":{"description":"External Record Link list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: cases:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Case not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Case identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.listCaseExternalRecordLinks","x-llm-guidance":"List External Record Links on a Case. Use an organization API key with cases:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/cases/$SOLAROS_CASE/external-record-links\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/cases/${process.env.SOLAROS_CASE}/external-record-links`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/cases/{os.environ['SOLAROS_CASE']}/external-record-links\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-case-external-record-links","groupSlug":"cases","navigationGroup":"Cases","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"post":{"operationId":"createCaseExternalRecordLink","tags":["Cases"],"summary":"Create or update an External Record Link on a Case","description":"Creates a navigable context link on the Case, or updates labels and data when the same URL is already linked. Requires Idempotency-Key and cases:write.","x-required-scopes":["cases:write"],"x-idempotency-key":"required","responses":{"200":{"description":"Updated External Record Link envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"201":{"description":"Created External Record Link envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation or idempotency error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: cases:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Case not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Case identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for createCaseExternalRecordLink.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["externalSystem","externalSystemLabel","objectLabel","recordLabel","url"],"properties":{"externalSystem":{"type":"string"},"externalSystemLabel":{"type":"string"},"objectLabel":{"type":"string"},"recordLabel":{"type":"string"},"url":{"type":"string","format":"uri"},"externalId":{"type":["string","null"]},"data":{"type":"object","additionalProperties":true}}},"examples":{"createcaseexternalrecordlinkRequest":{"value":{"externalSystem":"salesforce","externalSystemLabel":"Salesforce","objectLabel":"Account","recordLabel":"Paul Mundell","url":"https://example.my.salesforce.com/lightning/r/Account/001.../view"}}}}}},"x-tool-name":"orgApi.createCaseExternalRecordLink","x-llm-guidance":"Create or update an External Record Link on a Case. Use an organization API key with cases:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/cases/$SOLAROS_CASE/external-record-links\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"externalSystem\":\"salesforce\",\"externalSystemLabel\":\"Salesforce\",\"objectLabel\":\"Account\",\"recordLabel\":\"Paul Mundell\",\"url\":\"https://example.my.salesforce.com/lightning/r/Account/001.../view\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/cases/${process.env.SOLAROS_CASE}/external-record-links`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"externalSystem\": \"salesforce\",\n    \"externalSystemLabel\": \"Salesforce\",\n    \"objectLabel\": \"Account\",\n    \"recordLabel\": \"Paul Mundell\",\n    \"url\": \"https://example.my.salesforce.com/lightning/r/Account/001.../view\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/cases/{os.environ['SOLAROS_CASE']}/external-record-links\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"externalSystem\": \"salesforce\",\n  \"externalSystemLabel\": \"Salesforce\",\n  \"objectLabel\": \"Account\",\n  \"recordLabel\": \"Paul Mundell\",\n  \"url\": \"https://example.my.salesforce.com/lightning/r/Account/001.../view\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-case-external-record-link","groupSlug":"cases","navigationGroup":"Cases","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/cases/{id}/external-record-links/{linkId}":{"delete":{"operationId":"deleteCaseExternalRecordLink","tags":["Cases"],"summary":"Delete an External Record Link from a Case","description":"Deletes a tenant-scoped context link without changing the Case, the related external record, or any External Reference.","x-required-scopes":["cases:write"],"responses":{"204":{"description":"External Record Link deleted"},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: cases:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Case or External Record Link not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Case identifier returned by the Organization API.","schema":{"type":"string"}},{"name":"linkId","in":"path","required":true,"description":"LINK ID path identifier.","schema":{"type":"string"}}],"x-tool-name":"orgApi.deleteCaseExternalRecordLink","x-llm-guidance":"Delete an External Record Link from a Case. Use an organization API key with cases:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X DELETE \"$SOLAROS_BASE_URL/api/v1/cases/$SOLAROS_CASE/external-record-links/$SOLAROS_LINK_ID\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/cases/${process.env.SOLAROS_CASE}/external-record-links/${process.env.SOLAROS_LINK_ID}`, {\n  method: 'DELETE',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"DELETE\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/cases/{os.environ['SOLAROS_CASE']}/external-record-links/{os.environ['SOLAROS_LINK_ID']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"delete-case-external-record-link","groupSlug":"cases","navigationGroup":"Cases","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/work-orders":{"get":{"operationId":"listWorkOrders","tags":["Work Orders"],"summary":"List project-contained Work Orders","description":"Lists public API Work Orders that are contained in Projects. This endpoint only returns Work Orders that belong to a Project. Each Work Order carries its customer { id, displayName } (the Project's customer), scopeItems, and url, the Work Order page in solarOS. Filter by visit date with scheduledFrom and scheduledTo. Supply externalSystem, externalObject, and externalId together to filter by a canonical External Reference. Required scope: work_orders:read.","x-required-scopes":["work_orders:read"],"parameters":[{"name":"limit","in":"query","required":false,"description":"Maximum records to return. Defaults to 50 and is capped at 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Opaque record cursor from the previous response meta.nextCursor value.","schema":{"type":"string"}},{"name":"sortDir","in":"query","required":false,"description":"Sort direction. Defaults to desc.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"projectId","in":"query","required":false,"description":"Filter by containing Project id.","schema":{"type":"string"}},{"name":"workTypeId","in":"query","required":false,"description":"Filter by Work Type id.","schema":{"type":"string"}},{"name":"scheduledFrom","in":"query","required":false,"description":"ISO 8601 date-time. Only Work Orders with a visit (a Service Appointment that is not canceled) starting at or after this time. May be sent without scheduledTo.","schema":{"type":"string","format":"date-time"}},{"name":"scheduledTo","in":"query","required":false,"description":"ISO 8601 date-time. Only Work Orders with a visit (a Service Appointment that is not canceled) starting before this time. With scheduledFrom, the same visit must start inside both bounds.","schema":{"type":"string","format":"date-time"}},{"name":"status","in":"query","required":false,"description":"Filter by Work Order status.","schema":{"type":"string","enum":["NOT_READY_TO_SCHEDULE","READY_TO_SCHEDULE","SCHEDULED","IN_PROGRESS","COMPLETED","CANCELED"]}},{"name":"externalSystem","in":"query","required":false,"description":"External Reference system filter. Supply with externalObject and externalId for exact reconciliation lookup.","schema":{"type":"string"}},{"name":"externalObject","in":"query","required":false,"description":"External Reference object filter. Supply with externalSystem and externalId.","schema":{"type":"string"}},{"name":"externalId","in":"query","required":false,"description":"External Reference id filter. Supply with externalSystem and externalObject.","schema":{"type":"string"}}],"responses":{"200":{"description":"Work Order list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"400":{"description":"An unsupported status, or a scheduledFrom or scheduledTo that is not a date-time","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: work_orders:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.listWorkOrders","x-llm-guidance":"List project-contained Work Orders. Use an organization API key with work_orders:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/work-orders\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/work-orders`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/work-orders\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-work-orders","groupSlug":"work-orders","navigationGroup":"Work Orders","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"post":{"operationId":"createWorkOrder","tags":["Work Orders"],"summary":"Create a project-contained Work Order","description":"Creates a Work Order inside a required Project using an active Work Type. The Work Order Property is derived from the Project and submitted mismatches fail validation. Requires linking an existing unlinked WORK_ORDER Project Item or creating a limited inline Project Item in the same transaction. Scheduling fields are not writable. Requires Idempotency-Key and work_orders:write. notes is rejected: Work Order Notes was retired on 2026-10-27; send job instructions in description.","x-required-scopes":["work_orders:write"],"x-idempotency-key":"required","responses":{"201":{"description":"Created Work Order envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation, Project Item, stage, or idempotency error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: work_orders:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Project, Work Type, Project Item, or Stage not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Idempotency or External Reference conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for createWorkOrder.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["projectId","workTypeId","title"],"properties":{"projectId":{"type":"string"},"workTypeId":{"type":"string"},"title":{"type":"string"},"description":{"type":["string","null"]},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH","URGENT"]},"status":{"type":"string","enum":["NOT_READY_TO_SCHEDULE","READY_TO_SCHEDULE","BLOCKED","SCHEDULED","IN_PROGRESS"]},"estimatedHours":{"type":["string","number","null"]},"propertyId":{"type":["string","null"]},"projectItemId":{"type":["string","null"]},"projectItem":{"type":"object","additionalProperties":false,"properties":{"stageId":{"type":["string","null"]},"name":{"type":"string"},"description":{"type":["string","null"]},"sortOrder":{"type":"integer"},"isRequired":{"type":"boolean"},"isCustomerVisible":{"type":"boolean"},"customerFacingName":{"type":["string","null"]}}},"customFields":{"type":"object","additionalProperties":true,"description":"Field Values keyed by savedIdentity from GET /api/v1/schema."},"externalReferences":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}},"workOrderNumber":{"type":"string"}}},"examples":{"createworkorderRequest":{"value":{"projectId":"project_123","workTypeId":"work_type_123","title":"Install PV array","description":"Roof work and inverter installation.","priority":"MEDIUM","projectItem":{"name":"Install PV array","isRequired":true}}}}}}},"x-tool-name":"orgApi.createWorkOrder","x-llm-guidance":"Create a project-contained Work Order. Use an organization API key with work_orders:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/work-orders\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"projectId\":\"project_123\",\"workTypeId\":\"work_type_123\",\"title\":\"Install PV array\",\"description\":\"Roof work and inverter installation.\",\"priority\":\"MEDIUM\",\"projectItem\":{\"name\":\"Install PV array\",\"isRequired\":true}}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/work-orders`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"projectId\": \"project_123\",\n    \"workTypeId\": \"work_type_123\",\n    \"title\": \"Install PV array\",\n    \"description\": \"Roof work and inverter installation.\",\n    \"priority\": \"MEDIUM\",\n    \"projectItem\": {\n      \"name\": \"Install PV array\",\n      \"isRequired\": true\n    }\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/work-orders\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"projectId\": \"project_123\",\n  \"workTypeId\": \"work_type_123\",\n  \"title\": \"Install PV array\",\n  \"description\": \"Roof work and inverter installation.\",\n  \"priority\": \"MEDIUM\",\n  \"projectItem\": {\n    \"name\": \"Install PV array\",\n    \"isRequired\": true\n  }\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-work-order","groupSlug":"work-orders","navigationGroup":"Work Orders","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/work-orders/{id}":{"get":{"operationId":"getWorkOrder","tags":["Work Orders"],"summary":"Get one project-contained Work Order","description":"Returns Work Order details including workOrderNumber, customer { id, displayName } (the Project's customer), scopeItems, url (the Work Order page in solarOS), and schedulingContext, the nullable dispatcher-facing access, timing, and coordination instructions shared across appointments. Text formatting is preserved.","x-required-scopes":["work_orders:read"],"responses":{"200":{"description":"Work Order envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: work_orders:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Work Order identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getWorkOrder","x-llm-guidance":"Get one project-contained Work Order. Use an organization API key with work_orders:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/work-orders/$SOLAROS_WORK_ORDER\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/work-orders/${process.env.SOLAROS_WORK_ORDER}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/work-orders/{os.environ['SOLAROS_WORK_ORDER']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-work-order","groupSlug":"work-orders","navigationGroup":"Work Orders","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"patch":{"operationId":"updateWorkOrder","tags":["Work Orders"],"summary":"Update editable Work Order metadata","description":"Updates non-terminal Work Order metadata and customFields. Ownership is inherited from the containing Project and ownerId is rejected. Completion, cancellation, and scheduling remain explicit domain actions. notes is rejected: Work Order Notes was retired on 2026-10-27; send job instructions in description.","x-required-scopes":["work_orders:write"],"responses":{"200":{"description":"Updated Work Order envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: work_orders:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Work Order identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for updateWorkOrder.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"title":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":"string","enum":["NOT_READY_TO_SCHEDULE","READY_TO_SCHEDULE","SCHEDULED","IN_PROGRESS"]},"priority":{"type":"string","enum":["LOW","MEDIUM","HIGH","URGENT"]},"estimatedHours":{"type":["string","number","null"]},"customFields":{"type":"object","additionalProperties":true,"description":"Field Values keyed by savedIdentity from GET /api/v1/schema."}}},"examples":{"updateworkorderRequest":{"value":{"title":"Install PV array and inverter","priority":"HIGH"}}}}}},"x-tool-name":"orgApi.updateWorkOrder","x-llm-guidance":"Update editable Work Order metadata. Use an organization API key with work_orders:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/work-orders/$SOLAROS_WORK_ORDER\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"title\":\"Install PV array and inverter\",\"priority\":\"HIGH\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/work-orders/${process.env.SOLAROS_WORK_ORDER}`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"title\": \"Install PV array and inverter\",\n    \"priority\": \"HIGH\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/work-orders/{os.environ['SOLAROS_WORK_ORDER']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"title\": \"Install PV array and inverter\",\n  \"priority\": \"HIGH\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"update-work-order","groupSlug":"work-orders","navigationGroup":"Work Orders","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/work-orders/{id}/complete":{"post":{"operationId":"completeWorkOrder","tags":["Work Order Actions"],"summary":"Complete a Work Order","description":"Explicitly completes a project-contained Work Order through app domain services. Requires Idempotency-Key. Side effects include entitlement fulfillment sync, Project Item sync, audit, domain event, usage, and action response. Required scope: work_orders:complete.","x-required-scopes":["work_orders:complete"],"x-idempotency-key":"required","responses":{"200":{"description":"Work Order completion action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: work_orders:complete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Work Order identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for completeWorkOrder.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"completedDate":{"type":["string","null"]},"notes":{"type":["string","null"]}}},"examples":{"completeworkorderRequest":{"value":{"completedDate":"2026-08-12","notes":"Install completed and photos uploaded."}}}}}},"x-tool-name":"orgApi.completeWorkOrder","x-llm-guidance":"Complete a Work Order. Use an organization API key with work_orders:complete. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/work-orders/$SOLAROS_WORK_ORDER/complete\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"completedDate\":\"2026-08-12\",\"notes\":\"Install completed and photos uploaded.\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/work-orders/${process.env.SOLAROS_WORK_ORDER}/complete`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"completedDate\": \"2026-08-12\",\n    \"notes\": \"Install completed and photos uploaded.\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/work-orders/{os.environ['SOLAROS_WORK_ORDER']}/complete\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"completedDate\": \"2026-08-12\",\n  \"notes\": \"Install completed and photos uploaded.\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"complete-work-order","groupSlug":"work-order-actions","navigationGroup":"Work Order Actions","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/work-orders/{id}/cancel":{"post":{"operationId":"cancelWorkOrder","tags":["Work Order Actions"],"summary":"Cancel a Work Order","description":"Explicitly cancels a project-contained Work Order through app domain services. Requires Idempotency-Key. Side effects include entitlement unlink/sync, Project Item sync, audit, domain event, usage, and action response. Required scope: work_orders:cancel. reason is stored as the Work Order's cancelReason.","x-required-scopes":["work_orders:cancel"],"x-idempotency-key":"required","responses":{"200":{"description":"Work Order cancellation action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: work_orders:cancel","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Work Order identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for cancelWorkOrder.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"reason":{"type":["string","null"]}}},"examples":{"cancelworkorderRequest":{"value":{"reason":"Customer requested reschedule."}}}}}},"x-tool-name":"orgApi.cancelWorkOrder","x-llm-guidance":"Cancel a Work Order. Use an organization API key with work_orders:cancel. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/work-orders/$SOLAROS_WORK_ORDER/cancel\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"reason\":\"Customer requested reschedule.\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/work-orders/${process.env.SOLAROS_WORK_ORDER}/cancel`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"reason\": \"Customer requested reschedule.\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/work-orders/{os.environ['SOLAROS_WORK_ORDER']}/cancel\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"reason\": \"Customer requested reschedule.\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"cancel-work-order","groupSlug":"work-order-actions","navigationGroup":"Work Order Actions","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/material-reqs":{"get":{"operationId":"listMaterialReqs","tags":["Material Requests"],"summary":"List Material Requests","description":"Lists the organization's Material Requests — the materials ordered for project work, tracked through ordering, receipt, and pickup — with their line items. Filter by workOrderId, projectId (a request is on a Project through its project step or its Work Order), status, or updatedSince for incremental sync; a change to a line item counts as a change to its request. Deleted requests are not returned; a cancelled request has status CANCELLED. Required scope: material_reqs:read.","x-required-scopes":["material_reqs:read"],"parameters":[{"name":"limit","in":"query","required":false,"description":"Maximum records to return. Defaults to 50 and is capped at 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Opaque record cursor from the previous response meta.nextCursor value.","schema":{"type":"string"}},{"name":"sortDir","in":"query","required":false,"description":"Sort direction. Defaults to desc.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"workOrderId","in":"query","required":false,"description":"Only Material Requests for this Work Order.","schema":{"type":"string"}},{"name":"projectId","in":"query","required":false,"description":"Only Material Requests on this Project.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Filter by Material Request status.","schema":{"type":"string","enum":["PENDING","ORDERED","PARTIALLY_RECEIVED","RECEIVED","READY_FOR_PICKUP","PICKED_UP","CANCELLED"]}},{"name":"updatedSince","in":"query","required":false,"description":"ISO 8601 date-time with Z or a UTC offset. Only Material Requests changed at or after this time, including changes to their line items.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Material Request list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaterialRequestListEnvelope"}}}},"400":{"description":"UNSUPPORTED_FILTER: an unknown status. VALIDATION_FAILED: an updatedSince that is not a date-time with Z or a UTC offset.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: material_reqs:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.listMaterialReqs","x-llm-guidance":"List Material Requests. Use an organization API key with material_reqs:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/material-reqs\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/material-reqs`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/material-reqs\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-material-reqs","groupSlug":"material-requests","navigationGroup":"Material Requests","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"post":{"operationId":"createMaterialReq","tags":["Material Requests"],"summary":"Create a Material Request","description":"Creates a Material Request for a project-contained Work Order (workOrderId) or for a Project (projectId), with optional line items and order details. Like a request made in solarOS, it gets a Record Number and a step on the Project so it shows in the Project's materials. A status other than PENDING moves that step as it would in solarOS. pickupLocationId must be from GET /pickup-locations, and a line's productId must be a Product in this organization's catalog. estimatedCost is computed from the line items. Requires Idempotency-Key and material_reqs:write.","x-required-scopes":["material_reqs:write"],"x-idempotency-key":"required","responses":{"201":{"description":"Created Material Request envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaterialRequestEnvelope"}}}},"400":{"description":"Validation error: neither workOrderId nor projectId, a projectId that is not the Work Order's Project, a pickup Location that is archived or not open for pickup, or a missing Idempotency-Key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: material_reqs:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Work Order, Project, pickup Location, or Product not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for createMaterialReq.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"workOrderId":{"type":"string","description":"A project-contained Work Order. The request also shows on its Project."},"projectId":{"type":"string","description":"The Project, for a request that isn't for one Work Order. With workOrderId it must be the Work Order's Project."},"status":{"type":"string","enum":["PENDING","ORDERED","PARTIALLY_RECEIVED","RECEIVED","READY_FOR_PICKUP","PICKED_UP","CANCELLED"],"description":"A change moves the request's project step as it would in solarOS. PICKED_UP stamps pickedUpAt and marks pending and ordered line items picked up."},"neededByDate":{"type":["string","null"],"description":"A day: YYYY-MM-DD, saved as midnight UTC the way solarOS's date pickers save it, or an ISO 8601 date-time."},"vendorName":{"type":["string","null"]},"vendorOrderRef":{"type":["string","null"],"description":"The vendor's order or PO number."},"orderedDate":{"type":["string","null"],"description":"A day: YYYY-MM-DD, saved as midnight UTC the way solarOS's date pickers save it, or an ISO 8601 date-time."},"expectedDate":{"type":["string","null"],"description":"A day: YYYY-MM-DD, saved as midnight UTC the way solarOS's date pickers save it, or an ISO 8601 date-time."},"receivedDate":{"type":["string","null"],"description":"A day: YYYY-MM-DD, saved as midnight UTC the way solarOS's date pickers save it, or an ISO 8601 date-time."},"actualCost":{"type":["number","null"]},"pickupLocationId":{"type":["string","null"],"description":"An id from GET /pickup-locations."},"notes":{"type":["string","null"]},"lineItems":{"type":"array","maxItems":100,"items":{"type":"object","additionalProperties":false,"required":["name","quantity"],"properties":{"name":{"type":"string"},"quantity":{"type":"integer","minimum":1},"unit":{"type":"string","description":"Defaults to each."},"productId":{"type":["string","null"],"description":"A Product in this organization's catalog."},"description":{"type":["string","null"]},"unitCost":{"type":["number","null"]}}}}},"anyOf":[{"required":["workOrderId"]},{"required":["projectId"]}]},"examples":{"creatematerialreqRequest":{"value":{"workOrderId":"work_order_123","status":"ORDERED","vendorName":"CED Greentech","vendorOrderRef":"SO-88123","orderedDate":"2026-10-29","neededByDate":"2026-11-04","pickupLocationId":"location_123","lineItems":[{"name":"Powerwall 3","quantity":1,"unitCost":9850}]}}}}}},"x-tool-name":"orgApi.createMaterialReq","x-llm-guidance":"Create a Material Request. Use an organization API key with material_reqs:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/material-reqs\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"workOrderId\":\"work_order_123\",\"status\":\"ORDERED\",\"vendorName\":\"CED Greentech\",\"vendorOrderRef\":\"SO-88123\",\"orderedDate\":\"2026-10-29\",\"neededByDate\":\"2026-11-04\",\"pickupLocationId\":\"location_123\",\"lineItems\":[{\"name\":\"Powerwall 3\",\"quantity\":1,\"unitCost\":9850}]}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/material-reqs`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"workOrderId\": \"work_order_123\",\n    \"status\": \"ORDERED\",\n    \"vendorName\": \"CED Greentech\",\n    \"vendorOrderRef\": \"SO-88123\",\n    \"orderedDate\": \"2026-10-29\",\n    \"neededByDate\": \"2026-11-04\",\n    \"pickupLocationId\": \"location_123\",\n    \"lineItems\": [\n      {\n        \"name\": \"Powerwall 3\",\n        \"quantity\": 1,\n        \"unitCost\": 9850\n      }\n    ]\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/material-reqs\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"workOrderId\": \"work_order_123\",\n  \"status\": \"ORDERED\",\n  \"vendorName\": \"CED Greentech\",\n  \"vendorOrderRef\": \"SO-88123\",\n  \"orderedDate\": \"2026-10-29\",\n  \"neededByDate\": \"2026-11-04\",\n  \"pickupLocationId\": \"location_123\",\n  \"lineItems\": [\n    {\n      \"name\": \"Powerwall 3\",\n      \"quantity\": 1,\n      \"unitCost\": 9850\n    }\n  ]\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-material-req","groupSlug":"material-requests","navigationGroup":"Material Requests","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/material-reqs/{id}":{"get":{"operationId":"getMaterialReq","tags":["Material Requests"],"summary":"Get one Material Request","description":"Returns one Material Request with its pickup Location, Work Order, Project, and line items. Required scope: material_reqs:read.","x-required-scopes":["material_reqs:read"],"responses":{"200":{"description":"Material Request envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaterialRequestEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: material_reqs:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Material Req identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getMaterialReq","x-llm-guidance":"Get one Material Request. Use an organization API key with material_reqs:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/material-reqs/$SOLAROS_MATERIAL_REQ\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/material-reqs/${process.env.SOLAROS_MATERIAL_REQ}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/material-reqs/{os.environ['SOLAROS_MATERIAL_REQ']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-material-req","groupSlug":"material-requests","navigationGroup":"Material Requests","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"patch":{"operationId":"updateMaterialReq","tags":["Material Requests"],"summary":"Update a Material Request","description":"Records order progress made outside solarOS: status, vendor, order reference, dates, actual cost, pickup Location, and notes. Only fields sent are changed; meta.changedFields lists what changed, and a request whose values already match is not written. A status change moves the request's project step as it would in solarOS. Moving to PICKED_UP stamps pickedUpAt, leaves pickedUpBy empty, and marks pending and ordered line items picked up. Line items and the Work Order link are not changed here. Required scope: material_reqs:write.","x-required-scopes":["material_reqs:write"],"responses":{"200":{"description":"Updated Material Request envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MaterialRequestEnvelope"}}}},"400":{"description":"Validation error, or a pickup Location that is archived or not open for pickup","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: material_reqs:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Material Request or pickup Location not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Material Req identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for updateMaterialReq.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"status":{"type":"string","enum":["PENDING","ORDERED","PARTIALLY_RECEIVED","RECEIVED","READY_FOR_PICKUP","PICKED_UP","CANCELLED"],"description":"A change moves the request's project step as it would in solarOS. PICKED_UP stamps pickedUpAt and marks pending and ordered line items picked up."},"neededByDate":{"type":["string","null"],"description":"A day: YYYY-MM-DD, saved as midnight UTC the way solarOS's date pickers save it, or an ISO 8601 date-time."},"vendorName":{"type":["string","null"]},"vendorOrderRef":{"type":["string","null"],"description":"The vendor's order or PO number."},"orderedDate":{"type":["string","null"],"description":"A day: YYYY-MM-DD, saved as midnight UTC the way solarOS's date pickers save it, or an ISO 8601 date-time."},"expectedDate":{"type":["string","null"],"description":"A day: YYYY-MM-DD, saved as midnight UTC the way solarOS's date pickers save it, or an ISO 8601 date-time."},"receivedDate":{"type":["string","null"],"description":"A day: YYYY-MM-DD, saved as midnight UTC the way solarOS's date pickers save it, or an ISO 8601 date-time."},"actualCost":{"type":["number","null"]},"pickupLocationId":{"type":["string","null"],"description":"An id from GET /pickup-locations."},"notes":{"type":["string","null"]}}},"examples":{"updatematerialreqRequest":{"value":{"status":"READY_FOR_PICKUP","expectedDate":"2026-11-03","actualCost":9725.5,"pickupLocationId":"location_123"}}}}}},"x-tool-name":"orgApi.updateMaterialReq","x-llm-guidance":"Update a Material Request. Use an organization API key with material_reqs:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/material-reqs/$SOLAROS_MATERIAL_REQ\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"status\":\"READY_FOR_PICKUP\",\"expectedDate\":\"2026-11-03\",\"actualCost\":9725.5,\"pickupLocationId\":\"location_123\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/material-reqs/${process.env.SOLAROS_MATERIAL_REQ}`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"status\": \"READY_FOR_PICKUP\",\n    \"expectedDate\": \"2026-11-03\",\n    \"actualCost\": 9725.5,\n    \"pickupLocationId\": \"location_123\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/material-reqs/{os.environ['SOLAROS_MATERIAL_REQ']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"status\": \"READY_FOR_PICKUP\",\n  \"expectedDate\": \"2026-11-03\",\n  \"actualCost\": 9725.5,\n  \"pickupLocationId\": \"location_123\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"update-material-req","groupSlug":"material-requests","navigationGroup":"Material Requests","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/pickup-locations":{"get":{"operationId":"listPickupLocations","tags":["Material Requests"],"summary":"List pickup Locations","description":"Lists the organization's active Locations open for material pickup — the values a Material Request's pickupLocationId accepts — ordered as they are in solarOS settings. Required scope: material_reqs:read.","x-required-scopes":["material_reqs:read"],"responses":{"200":{"description":"Pickup Location list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PickupLocationListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: material_reqs:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"x-tool-name":"orgApi.listPickupLocations","x-llm-guidance":"List pickup Locations. Use an organization API key with material_reqs:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/pickup-locations\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/pickup-locations`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/pickup-locations\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-pickup-locations","groupSlug":"material-requests","navigationGroup":"Material Requests","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/service-appointments":{"get":{"operationId":"listServiceAppointments","tags":["Service Appointments"],"summary":"List Service Appointments","description":"Lists Service Appointments tied to public API-accessible project-contained Work Orders. Supports Work Order, status, Team Member, and interval-overlap filters. Required scope: service_appointments:read.","x-required-scopes":["service_appointments:read"],"parameters":[{"name":"limit","in":"query","required":false,"description":"Maximum records to return. Defaults to 50 and is capped at 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Opaque record cursor from the previous response meta.nextCursor value.","schema":{"type":"string"}},{"name":"sortDir","in":"query","required":false,"description":"Sort direction. Defaults to desc.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"workOrderId","in":"query","required":false,"description":"Filter by containing Work Order id.","schema":{"type":"string"}},{"name":"status","in":"query","required":false,"description":"Filter by exact operational status.","schema":{"type":"string","enum":["SCHEDULED","DISPATCHED","EN_ROUTE","IN_PROGRESS","COMPLETED","CANCELLED","CANNOT_COMPLETE"]}},{"name":"teamMemberId","in":"query","required":false,"description":"Filter to appointments assigned to this Team Member.","schema":{"type":"string"}},{"name":"dateStart","in":"query","required":false,"description":"ISO date-time lower bound. Returns appointments whose scheduled interval ends after this instant.","schema":{"type":"string","format":"date-time"}},{"name":"dateEnd","in":"query","required":false,"description":"ISO date-time upper bound. Returns appointments whose scheduled interval starts before this instant.","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"Service Appointment list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: service_appointments:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.listServiceAppointments","x-llm-guidance":"List Service Appointments. Use an organization API key with service_appointments:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/service-appointments\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/service-appointments`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/service-appointments\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-service-appointments","groupSlug":"service-appointments","navigationGroup":"Service Appointments","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"post":{"operationId":"createServiceAppointment","tags":["Service Appointments"],"summary":"Create a Service Appointment","description":"Creates one interval-first Service Appointment for an accessible Work Order. scheduledStart, scheduledEnd, and timezone are required; durationMinutes is derived. Optional estimatedDurationMinutes is accepted only when it exactly matches the interval. Customer-facing windows must contain the exact scheduled interval. Assignment requires active same-organization schedulable Team Members (Service Resources) and a primary member included in the assigned set. Overlaps return structured warnings and do not block writes by themselves. Requires Idempotency-Key and service_appointments:write.","x-required-scopes":["service_appointments:write"],"x-idempotency-key":"required","responses":{"201":{"description":"Created Service Appointment envelope with warnings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation or idempotency error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: service_appointments:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Work Order not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for createServiceAppointment.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["workOrderId","scheduledStart","scheduledEnd","timezone","assignedTeamMemberIds","primaryTeamMemberId"],"properties":{"workOrderId":{"type":"string"},"scheduledStart":{"type":"string","format":"date-time"},"scheduledEnd":{"type":"string","format":"date-time"},"timezone":{"type":"string"},"customerWindowStart":{"type":["string","null"],"format":"date-time"},"customerWindowEnd":{"type":["string","null"],"format":"date-time"},"assignedTeamMemberIds":{"type":"array","items":{"type":"string"}},"primaryTeamMemberId":{"type":"string"},"notes":{"type":["string","null"]},"schedulingConfidence":{"type":"string","enum":["TENTATIVELY_SCHEDULED","CONFIDENTLY_SCHEDULED","CONFIRMED"]},"estimatedDurationMinutes":{"type":"integer"}}},"examples":{"createserviceappointmentRequest":{"value":{"workOrderId":"work_order_123","scheduledStart":"2026-08-13T16:00:00Z","scheduledEnd":"2026-08-13T20:00:00Z","timezone":"America/Los_Angeles","assignedTeamMemberIds":["team_member_123"],"primaryTeamMemberId":"team_member_123"}}}}}},"x-tool-name":"orgApi.createServiceAppointment","x-llm-guidance":"Create a Service Appointment. Use an organization API key with service_appointments:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/service-appointments\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"workOrderId\":\"work_order_123\",\"scheduledStart\":\"2026-08-13T16:00:00Z\",\"scheduledEnd\":\"2026-08-13T20:00:00Z\",\"timezone\":\"America/Los_Angeles\",\"assignedTeamMemberIds\":[\"team_member_123\"],\"primaryTeamMemberId\":\"team_member_123\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/service-appointments`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"workOrderId\": \"work_order_123\",\n    \"scheduledStart\": \"2026-08-13T16:00:00Z\",\n    \"scheduledEnd\": \"2026-08-13T20:00:00Z\",\n    \"timezone\": \"America/Los_Angeles\",\n    \"assignedTeamMemberIds\": [\n      \"team_member_123\"\n    ],\n    \"primaryTeamMemberId\": \"team_member_123\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/service-appointments\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"workOrderId\": \"work_order_123\",\n  \"scheduledStart\": \"2026-08-13T16:00:00Z\",\n  \"scheduledEnd\": \"2026-08-13T20:00:00Z\",\n  \"timezone\": \"America/Los_Angeles\",\n  \"assignedTeamMemberIds\": [\n    \"team_member_123\"\n  ],\n  \"primaryTeamMemberId\": \"team_member_123\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-service-appointment","groupSlug":"service-appointments","navigationGroup":"Service Appointments","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/service-appointments/multi-day":{"post":{"operationId":"createMultiDayServiceAppointments","tags":["Service Appointments"],"summary":"Create multi-day Service Appointments","description":"Creates one Service Appointment row per local day between startDate and endDate using shared daily schedule, Team Member assignment, primary member, timezone, notes, and confidence semantics. Requires Idempotency-Key and service_appointments:write.","x-required-scopes":["service_appointments:write"],"x-idempotency-key":"required","responses":{"201":{"description":"Multi-day Service Appointment envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: service_appointments:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for createMultiDayServiceAppointments.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["workOrderId","startDate","endDate","dailyStartTime","dailyEndTime","timezone","assignedTeamMemberIds","primaryTeamMemberId"],"properties":{"workOrderId":{"type":"string"},"startDate":{"type":"string","format":"date"},"endDate":{"type":"string","format":"date"},"dailyStartTime":{"type":"string"},"dailyEndTime":{"type":"string"},"timezone":{"type":"string"},"assignedTeamMemberIds":{"type":"array","items":{"type":"string"}},"primaryTeamMemberId":{"type":"string"},"notes":{"type":["string","null"]},"schedulingConfidence":{"type":"string","enum":["TENTATIVELY_SCHEDULED","CONFIDENTLY_SCHEDULED","CONFIRMED"]}}},"examples":{"createmultidayserviceappointmentsRequest":{"value":{"workOrderId":"work_order_123","startDate":"2026-08-13","endDate":"2026-08-15","dailyStartTime":"09:00","dailyEndTime":"15:00","timezone":"America/Los_Angeles","assignedTeamMemberIds":["team_member_123"],"primaryTeamMemberId":"team_member_123"}}}}}},"x-tool-name":"orgApi.createMultiDayServiceAppointments","x-llm-guidance":"Create multi-day Service Appointments. Use an organization API key with service_appointments:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/service-appointments/multi-day\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"workOrderId\":\"work_order_123\",\"startDate\":\"2026-08-13\",\"endDate\":\"2026-08-15\",\"dailyStartTime\":\"09:00\",\"dailyEndTime\":\"15:00\",\"timezone\":\"America/Los_Angeles\",\"assignedTeamMemberIds\":[\"team_member_123\"],\"primaryTeamMemberId\":\"team_member_123\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/service-appointments/multi-day`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"workOrderId\": \"work_order_123\",\n    \"startDate\": \"2026-08-13\",\n    \"endDate\": \"2026-08-15\",\n    \"dailyStartTime\": \"09:00\",\n    \"dailyEndTime\": \"15:00\",\n    \"timezone\": \"America/Los_Angeles\",\n    \"assignedTeamMemberIds\": [\n      \"team_member_123\"\n    ],\n    \"primaryTeamMemberId\": \"team_member_123\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/service-appointments/multi-day\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"workOrderId\": \"work_order_123\",\n  \"startDate\": \"2026-08-13\",\n  \"endDate\": \"2026-08-15\",\n  \"dailyStartTime\": \"09:00\",\n  \"dailyEndTime\": \"15:00\",\n  \"timezone\": \"America/Los_Angeles\",\n  \"assignedTeamMemberIds\": [\n    \"team_member_123\"\n  ],\n  \"primaryTeamMemberId\": \"team_member_123\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-multi-day-service-appointments","groupSlug":"service-appointments","navigationGroup":"Service Appointments","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/service-appointments/{id}":{"get":{"operationId":"getServiceAppointment","tags":["Service Appointments"],"summary":"Get one Service Appointment","x-required-scopes":["service_appointments:read"],"responses":{"200":{"description":"Service Appointment envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: service_appointments:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"description":"Get one Service Appointment","parameters":[{"name":"id","in":"path","required":true,"description":"Service Appointment identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getServiceAppointment","x-llm-guidance":"Get one Service Appointment. Use an organization API key with service_appointments:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/service-appointments/$SOLAROS_SERVICE_APPOINTMENT\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/service-appointments/${process.env.SOLAROS_SERVICE_APPOINTMENT}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/service-appointments/{os.environ['SOLAROS_SERVICE_APPOINTMENT']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-service-appointment","groupSlug":"service-appointments","navigationGroup":"Service Appointments","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"patch":{"operationId":"updateServiceAppointment","tags":["Service Appointments"],"summary":"Update schedule, assignment, notes, confidence, or window","description":"Updates rescheduling fields, assignment changes, notes, scheduling confidence, and customer-facing windows. Direct operational status writes are rejected; use action endpoints instead. Scheduling confidence wire values are TENTATIVELY_SCHEDULED, CONFIDENTLY_SCHEDULED, and CONFIRMED.","x-required-scopes":["service_appointments:write"],"responses":{"200":{"description":"Updated Service Appointment envelope with warnings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: service_appointments:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Lifecycle conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Service Appointment identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for updateServiceAppointment.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"scheduledStart":{"type":"string","format":"date-time"},"scheduledEnd":{"type":"string","format":"date-time"},"timezone":{"type":"string"},"customerWindowStart":{"type":["string","null"],"format":"date-time"},"customerWindowEnd":{"type":["string","null"],"format":"date-time"},"assignedTeamMemberIds":{"type":"array","items":{"type":"string"}},"primaryTeamMemberId":{"type":"string"},"notes":{"type":["string","null"]},"schedulingConfidence":{"type":"string","enum":["TENTATIVELY_SCHEDULED","CONFIDENTLY_SCHEDULED","CONFIRMED"]}}},"examples":{"updateserviceappointmentRequest":{"value":{"scheduledStart":"2026-08-13T17:00:00Z","scheduledEnd":"2026-08-13T21:00:00Z","timezone":"America/Los_Angeles","notes":"Customer gate code is in the Work Order description."}}}}}},"x-tool-name":"orgApi.updateServiceAppointment","x-llm-guidance":"Update schedule, assignment, notes, confidence, or window. Use an organization API key with service_appointments:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/service-appointments/$SOLAROS_SERVICE_APPOINTMENT\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"scheduledStart\":\"2026-08-13T17:00:00Z\",\"scheduledEnd\":\"2026-08-13T21:00:00Z\",\"timezone\":\"America/Los_Angeles\",\"notes\":\"Customer gate code is in the Work Order description.\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/service-appointments/${process.env.SOLAROS_SERVICE_APPOINTMENT}`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"scheduledStart\": \"2026-08-13T17:00:00Z\",\n    \"scheduledEnd\": \"2026-08-13T21:00:00Z\",\n    \"timezone\": \"America/Los_Angeles\",\n    \"notes\": \"Customer gate code is in the Work Order description.\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/service-appointments/{os.environ['SOLAROS_SERVICE_APPOINTMENT']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"scheduledStart\": \"2026-08-13T17:00:00Z\",\n  \"scheduledEnd\": \"2026-08-13T21:00:00Z\",\n  \"timezone\": \"America/Los_Angeles\",\n  \"notes\": \"Customer gate code is in the Work Order description.\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"update-service-appointment","groupSlug":"service-appointments","navigationGroup":"Service Appointments","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"delete":{"operationId":"deleteServiceAppointment","tags":["Service Appointments"],"summary":"Delete an unstarted or cancelled calendar booking","description":"Hard-deletes a calendar booking only before execution starts or after cancellation. Requires Idempotency-Key, emits audit/domain events, and removes the record from normal reads. The booking's draft report is soft-deleted when nothing has been entered in it; a draft with any work in it stays on the work order without a booking. Required scope: service_appointments:delete.","x-required-scopes":["service_appointments:delete"],"x-idempotency-key":"required","responses":{"200":{"description":"Delete action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: service_appointments:delete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Execution already started","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Service Appointment identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.deleteServiceAppointment","x-llm-guidance":"Delete an unstarted or cancelled calendar booking. Use an organization API key with service_appointments:delete. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X DELETE \"$SOLAROS_BASE_URL/api/v1/service-appointments/$SOLAROS_SERVICE_APPOINTMENT\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/service-appointments/${process.env.SOLAROS_SERVICE_APPOINTMENT}`, {\n  method: 'DELETE',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"DELETE\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/service-appointments/{os.environ['SOLAROS_SERVICE_APPOINTMENT']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"delete-service-appointment","groupSlug":"service-appointments","navigationGroup":"Service Appointments","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/service-appointments/{id}/dispatch":{"post":{"operationId":"dispatchServiceAppointment","tags":["Service Appointment Actions"],"summary":"Dispatch a Service Appointment","description":"Transitions a scheduled appointment to DISPATCHED. The body is optional. Accepted body fields are ignored by this action but still participate in idempotency matching; prefer an empty object.","x-required-scopes":["service_appointments:dispatch"],"x-idempotency-key":"required","responses":{"200":{"description":"Dispatch action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: service_appointments:dispatch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Service Appointment identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":false,"description":"JSON request payload for dispatchServiceAppointment.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"completedAt":{"type":["string","null"],"format":"date-time"},"notes":{"type":["string","null"]},"reason":{"type":"string","enum":["CUSTOMER_REQUEST","TECH_UNAVAILABLE","WEATHER","RESCHEDULED","NO_SHOW","OTHER"]}}},"examples":{"dispatchserviceappointmentRequest":{"value":{}}}}}},"x-tool-name":"orgApi.dispatchServiceAppointment","x-llm-guidance":"Dispatch a Service Appointment. Use an organization API key with service_appointments:dispatch. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/service-appointments/$SOLAROS_SERVICE_APPOINTMENT/dispatch\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/service-appointments/${process.env.SOLAROS_SERVICE_APPOINTMENT}/dispatch`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({}),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/service-appointments/{os.environ['SOLAROS_SERVICE_APPOINTMENT']}/dispatch\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"dispatch-service-appointment","groupSlug":"service-appointment-actions","navigationGroup":"Service Appointment Actions","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/service-appointments/{id}/en-route":{"post":{"operationId":"markServiceAppointmentEnRoute","tags":["Service Appointment Actions"],"summary":"Mark a Service Appointment en route","description":"Transitions a dispatched appointment to EN_ROUTE. The body is optional. Accepted body fields are ignored by this action but still participate in idempotency matching; prefer an empty object.","x-required-scopes":["service_appointments:start"],"x-idempotency-key":"required","responses":{"200":{"description":"En-route action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: service_appointments:start","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Service Appointment identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":false,"description":"JSON request payload for markServiceAppointmentEnRoute.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"completedAt":{"type":["string","null"],"format":"date-time"},"notes":{"type":["string","null"]},"reason":{"type":"string","enum":["CUSTOMER_REQUEST","TECH_UNAVAILABLE","WEATHER","RESCHEDULED","NO_SHOW","OTHER"]}}},"examples":{"markserviceappointmentenrouteRequest":{"value":{}}}}}},"x-tool-name":"orgApi.markServiceAppointmentEnRoute","x-llm-guidance":"Mark a Service Appointment en route. Use an organization API key with service_appointments:start. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/service-appointments/$SOLAROS_SERVICE_APPOINTMENT/en-route\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/service-appointments/${process.env.SOLAROS_SERVICE_APPOINTMENT}/en-route`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({}),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/service-appointments/{os.environ['SOLAROS_SERVICE_APPOINTMENT']}/en-route\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"mark-service-appointment-en-route","groupSlug":"service-appointment-actions","navigationGroup":"Service Appointment Actions","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/service-appointments/{id}/start":{"post":{"operationId":"startServiceAppointment","tags":["Service Appointment Actions"],"summary":"Start a Service Appointment","description":"Transitions an appointment to IN_PROGRESS. The body is optional. Accepted body fields are ignored by this action but still participate in idempotency matching; prefer an empty object.","x-required-scopes":["service_appointments:start"],"x-idempotency-key":"required","responses":{"200":{"description":"Start action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: service_appointments:start","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Service Appointment identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":false,"description":"JSON request payload for startServiceAppointment.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"completedAt":{"type":["string","null"],"format":"date-time"},"notes":{"type":["string","null"]},"reason":{"type":"string","enum":["CUSTOMER_REQUEST","TECH_UNAVAILABLE","WEATHER","RESCHEDULED","NO_SHOW","OTHER"]}}},"examples":{"startserviceappointmentRequest":{"value":{}}}}}},"x-tool-name":"orgApi.startServiceAppointment","x-llm-guidance":"Start a Service Appointment. Use an organization API key with service_appointments:start. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/service-appointments/$SOLAROS_SERVICE_APPOINTMENT/start\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/service-appointments/${process.env.SOLAROS_SERVICE_APPOINTMENT}/start`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({}),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/service-appointments/{os.environ['SOLAROS_SERVICE_APPOINTMENT']}/start\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"start-service-appointment","groupSlug":"service-appointment-actions","navigationGroup":"Service Appointment Actions","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/service-appointments/{id}/complete":{"post":{"operationId":"completeServiceAppointment","tags":["Service Appointment Actions"],"summary":"Complete a Service Appointment","description":"Transitions an in-progress appointment to COMPLETED. The optional body accepts completedAt and notes.","x-required-scopes":["service_appointments:complete"],"x-idempotency-key":"required","responses":{"200":{"description":"Complete action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: service_appointments:complete","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Service Appointment identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":false,"description":"JSON request payload for completeServiceAppointment.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"completedAt":{"type":["string","null"],"format":"date-time"},"notes":{"type":["string","null"]},"reason":{"type":"string","enum":["CUSTOMER_REQUEST","TECH_UNAVAILABLE","WEATHER","RESCHEDULED","NO_SHOW","OTHER"]}}},"examples":{"completeserviceappointmentRequest":{"value":{"completedAt":"2026-08-13T20:05:00Z","notes":"Work completed."}}}}}},"x-tool-name":"orgApi.completeServiceAppointment","x-llm-guidance":"Complete a Service Appointment. Use an organization API key with service_appointments:complete. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/service-appointments/$SOLAROS_SERVICE_APPOINTMENT/complete\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"completedAt\":\"2026-08-13T20:05:00Z\",\"notes\":\"Work completed.\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/service-appointments/${process.env.SOLAROS_SERVICE_APPOINTMENT}/complete`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"completedAt\": \"2026-08-13T20:05:00Z\",\n    \"notes\": \"Work completed.\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/service-appointments/{os.environ['SOLAROS_SERVICE_APPOINTMENT']}/complete\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"completedAt\": \"2026-08-13T20:05:00Z\",\n  \"notes\": \"Work completed.\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"complete-service-appointment","groupSlug":"service-appointment-actions","navigationGroup":"Service Appointment Actions","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/service-appointments/{id}/cancel":{"post":{"operationId":"cancelServiceAppointment","tags":["Service Appointment Actions"],"summary":"Cancel a Service Appointment","description":"Transitions an appointment to CANCELLED. The optional body accepts notes and a reason enum; it does not accept arbitrary timestamps or assignee fields.","x-required-scopes":["service_appointments:cancel"],"x-idempotency-key":"required","responses":{"200":{"description":"Cancel action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: service_appointments:cancel","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Service Appointment identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":false,"description":"JSON request payload for cancelServiceAppointment.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"completedAt":{"type":["string","null"],"format":"date-time"},"notes":{"type":["string","null"]},"reason":{"type":"string","enum":["CUSTOMER_REQUEST","TECH_UNAVAILABLE","WEATHER","RESCHEDULED","NO_SHOW","OTHER"]}}},"examples":{"cancelserviceappointmentRequest":{"value":{"reason":"WEATHER","notes":"Unsafe roof conditions."}}}}}},"x-tool-name":"orgApi.cancelServiceAppointment","x-llm-guidance":"Cancel a Service Appointment. Use an organization API key with service_appointments:cancel. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/service-appointments/$SOLAROS_SERVICE_APPOINTMENT/cancel\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"reason\":\"WEATHER\",\"notes\":\"Unsafe roof conditions.\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/service-appointments/${process.env.SOLAROS_SERVICE_APPOINTMENT}/cancel`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"reason\": \"WEATHER\",\n    \"notes\": \"Unsafe roof conditions.\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/service-appointments/{os.environ['SOLAROS_SERVICE_APPOINTMENT']}/cancel\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"reason\": \"WEATHER\",\n  \"notes\": \"Unsafe roof conditions.\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"cancel-service-appointment","groupSlug":"service-appointment-actions","navigationGroup":"Service Appointment Actions","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/service-appointments/{id}/issues":{"get":{"operationId":"listServiceAppointmentIssues","tags":["Service Appointment Issues"],"summary":"List Service Appointment issues","x-required-scopes":["service_appointments:issues:read"],"responses":{"200":{"description":"Issue list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: service_appointments:issues:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"description":"List Service Appointment issues","parameters":[{"name":"id","in":"path","required":true,"description":"Service Appointment identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.listServiceAppointmentIssues","x-llm-guidance":"List Service Appointment issues. Use an organization API key with service_appointments:issues:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/service-appointments/$SOLAROS_SERVICE_APPOINTMENT/issues\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/service-appointments/${process.env.SOLAROS_SERVICE_APPOINTMENT}/issues`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/service-appointments/{os.environ['SOLAROS_SERVICE_APPOINTMENT']}/issues\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-service-appointment-issues","groupSlug":"service-appointment-issues","navigationGroup":"Service Appointment Issues","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"post":{"operationId":"createServiceAppointmentIssue","tags":["Service Appointment Issues"],"summary":"Create a Service Appointment issue","description":"Creates a typed unresolved issue. The writable fields are issueType, notes, and reportedByTeamMemberId; severity, title, and description are not accepted.","x-required-scopes":["service_appointments:issues:write"],"x-idempotency-key":"required","responses":{"201":{"description":"Created issue envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: service_appointments:issues:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Service Appointment identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for createServiceAppointmentIssue.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["issueType"],"properties":{"issueType":{"type":"string","enum":["HOMEOWNER_NOT_HOME","ACCESS_ISSUE","UNSAFE_CONDITIONS","MISSING_EQUIPMENT","CUSTOMER_REFUSED","OTHER"]},"notes":{"type":["string","null"]},"reportedByTeamMemberId":{"type":"string"}}},"examples":{"createserviceappointmentissueRequest":{"value":{"issueType":"ACCESS_ISSUE","notes":"Property manager approval is required for roof access."}}}}}},"x-tool-name":"orgApi.createServiceAppointmentIssue","x-llm-guidance":"Create a Service Appointment issue. Use an organization API key with service_appointments:issues:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/service-appointments/$SOLAROS_SERVICE_APPOINTMENT/issues\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"issueType\":\"ACCESS_ISSUE\",\"notes\":\"Property manager approval is required for roof access.\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/service-appointments/${process.env.SOLAROS_SERVICE_APPOINTMENT}/issues`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"issueType\": \"ACCESS_ISSUE\",\n    \"notes\": \"Property manager approval is required for roof access.\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/service-appointments/{os.environ['SOLAROS_SERVICE_APPOINTMENT']}/issues\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"issueType\": \"ACCESS_ISSUE\",\n  \"notes\": \"Property manager approval is required for roof access.\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-service-appointment-issue","groupSlug":"service-appointment-issues","navigationGroup":"Service Appointment Issues","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/service-appointments/{id}/issues/{issueId}":{"patch":{"operationId":"updateServiceAppointmentIssue","tags":["Service Appointment Issues"],"summary":"Update an unresolved Service Appointment issue","description":"Updates issueType or notes. Resolved issues return a lifecycle conflict.","x-required-scopes":["service_appointments:issues:write"],"responses":{"200":{"description":"Updated issue envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: service_appointments:issues:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Issue already resolved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Service Appointment identifier returned by the Organization API.","schema":{"type":"string"}},{"name":"issueId","in":"path","required":true,"description":"ISSUE ID path identifier.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for updateServiceAppointmentIssue.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"issueType":{"type":"string","enum":["HOMEOWNER_NOT_HOME","ACCESS_ISSUE","UNSAFE_CONDITIONS","MISSING_EQUIPMENT","CUSTOMER_REFUSED","OTHER"]},"notes":{"type":["string","null"]}}},"examples":{"updateserviceappointmentissueRequest":{"value":{"notes":"Property manager approval is pending."}}}}}},"x-tool-name":"orgApi.updateServiceAppointmentIssue","x-llm-guidance":"Update an unresolved Service Appointment issue. Use an organization API key with service_appointments:issues:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/service-appointments/$SOLAROS_SERVICE_APPOINTMENT/issues/$SOLAROS_ISSUE_ID\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"notes\":\"Property manager approval is pending.\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/service-appointments/${process.env.SOLAROS_SERVICE_APPOINTMENT}/issues/${process.env.SOLAROS_ISSUE_ID}`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"notes\": \"Property manager approval is pending.\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/service-appointments/{os.environ['SOLAROS_SERVICE_APPOINTMENT']}/issues/{os.environ['SOLAROS_ISSUE_ID']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"notes\": \"Property manager approval is pending.\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"update-service-appointment-issue","groupSlug":"service-appointment-issues","navigationGroup":"Service Appointment Issues","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/service-appointments/{id}/issues/{issueId}/resolve":{"post":{"operationId":"resolveServiceAppointmentIssue","tags":["Service Appointment Issues"],"summary":"Resolve a Service Appointment issue","description":"Resolves the issue. The optional body may identify resolvedByTeamMemberId.","x-required-scopes":["service_appointments:issues:write"],"x-idempotency-key":"required","responses":{"200":{"description":"Resolve action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: service_appointments:issues:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Service Appointment identifier returned by the Organization API.","schema":{"type":"string"}},{"name":"issueId","in":"path","required":true,"description":"ISSUE ID path identifier.","schema":{"type":"string"}}],"requestBody":{"required":false,"description":"JSON request payload for resolveServiceAppointmentIssue.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"resolvedByTeamMemberId":{"type":"string"}}},"examples":{"resolveserviceappointmentissueRequest":{"value":{"resolvedByTeamMemberId":"team_member_123"}}}}}},"x-tool-name":"orgApi.resolveServiceAppointmentIssue","x-llm-guidance":"Resolve a Service Appointment issue. Use an organization API key with service_appointments:issues:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/service-appointments/$SOLAROS_SERVICE_APPOINTMENT/issues/$SOLAROS_ISSUE_ID/resolve\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"resolvedByTeamMemberId\":\"team_member_123\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/service-appointments/${process.env.SOLAROS_SERVICE_APPOINTMENT}/issues/${process.env.SOLAROS_ISSUE_ID}/resolve`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"resolvedByTeamMemberId\": \"team_member_123\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/service-appointments/{os.environ['SOLAROS_SERVICE_APPOINTMENT']}/issues/{os.environ['SOLAROS_ISSUE_ID']}/resolve\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"resolvedByTeamMemberId\": \"team_member_123\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"resolve-service-appointment-issue","groupSlug":"service-appointment-issues","navigationGroup":"Service Appointment Issues","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/quotes":{"get":{"operationId":"listQuotes","tags":["Quotes"],"summary":"List Quotes","description":"Lists Quotes inside the organization boundary with endpoint-declared filters, safe relations, customFields, and External References. Supply externalSystem, externalObject, and externalId together to filter by a canonical External Reference. Required scope: quotes:read.","x-required-scopes":["quotes:read"],"parameters":[{"name":"limit","in":"query","required":false,"description":"Maximum records to return. Defaults to 50 and is capped at 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Opaque record cursor from the previous response meta.nextCursor value.","schema":{"type":"string"}},{"name":"sortDir","in":"query","required":false,"description":"Sort direction. Defaults to desc.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"status","in":"query","required":false,"description":"Filter by exact Quote status.","schema":{"type":"string","enum":["DRAFT","PENDING_APPROVAL","SENT","VIEWED","ACCEPTED","REJECTED","EXPIRED","CANCELLED"]}},{"name":"customerId","in":"query","required":false,"description":"Filter by Customer id.","schema":{"type":"string"}},{"name":"propertyId","in":"query","required":false,"description":"Filter by Property id.","schema":{"type":"string"}},{"name":"opportunityId","in":"query","required":false,"description":"Filter by Opportunity id.","schema":{"type":"string"}},{"name":"ownerId","in":"query","required":false,"description":"Filter by owner Team Member id.","schema":{"type":"string"}},{"name":"quoteTypeId","in":"query","required":false,"description":"Filter by Company Quote Type id.","schema":{"type":"string"}},{"name":"externalSystem","in":"query","required":false,"description":"External Reference system filter. Supply with externalObject and externalId for exact reconciliation lookup.","schema":{"type":"string"}},{"name":"externalObject","in":"query","required":false,"description":"External Reference object filter. Supply with externalSystem and externalId.","schema":{"type":"string"}},{"name":"externalId","in":"query","required":false,"description":"External Reference id filter. Supply with externalSystem and externalObject.","schema":{"type":"string"}}],"responses":{"200":{"description":"Quote list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: quotes:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"x-tool-name":"orgApi.listQuotes","x-llm-guidance":"List Quotes. Use an organization API key with quotes:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/quotes\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/quotes`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/quotes\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-quotes","groupSlug":"quotes","navigationGroup":"Quotes","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"post":{"operationId":"createQuote","tags":["Quotes"],"summary":"Create a draft Quote","description":"Creates DRAFT Quotes only. Requires Idempotency-Key. Validates accessible Customer/Property/Opportunity, active Quote Type/Template, owner defaults, placed custom Fields, External References, audit, and domain events. ownerId is create-only in v1; generic Quote PATCH cannot reassign ownership. Without originatorId, the Quote takes its Opportunity's Originator, or credits its owner when it has no Opportunity. An answer in customFields to a Property Field (see isPropertyField) becomes the Property's answer, is recorded in its history, and fills that Field on the Property's draft Quotes and open Projects where it is still blank; a Quote Template's default is not an answer. Required scope: quotes:write.","x-required-scopes":["quotes:write"],"x-idempotency-key":"required","responses":{"201":{"description":"Created Quote envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation, owner, or custom Field error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: quotes:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Idempotency or External Reference conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[],"requestBody":{"required":true,"description":"JSON request payload for createQuote.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["name","customerId","quoteTypeId"],"properties":{"name":{"type":"string"},"customerId":{"type":"string"},"propertyId":{"type":["string","null"]},"opportunityId":{"type":["string","null"]},"quoteTypeId":{"type":"string"},"quoteTemplateId":{"type":["string","null"]},"validUntil":{"type":["string","null"]},"summary":{"type":["string","null"]},"notes":{"type":["string","null"]},"terms":{"type":["string","null"]},"ownerId":{"type":["string","null"],"description":"Active or draft same-organization Team Member id. When omitted, the API key default owner for this resource is used. Ownership cannot be changed through generic PATCH endpoints."},"originatorId":{"type":["string","null"],"description":"The active or draft same-organization Team Member credited with bringing this sale in. When omitted, the Quote takes its Opportunity's Originator, or credits its owner when it has no Opportunity."},"customFields":{"type":"object","additionalProperties":true,"description":"Field Values keyed by savedIdentity from GET /api/v1/schema."},"externalReferences":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"examples":{"createquoteRequest":{"value":{"customerId":"customer_123","propertyId":"property_123","opportunityId":"opportunity_123","quoteTypeId":"quote_type_123","quoteTemplateId":"quote_template_123","name":"8.4 kW solar proposal"}}}}}},"x-tool-name":"orgApi.createQuote","x-llm-guidance":"Create a draft Quote. Use an organization API key with quotes:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/quotes\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"customerId\":\"customer_123\",\"propertyId\":\"property_123\",\"opportunityId\":\"opportunity_123\",\"quoteTypeId\":\"quote_type_123\",\"quoteTemplateId\":\"quote_template_123\",\"name\":\"8.4 kW solar proposal\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/quotes`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"customerId\": \"customer_123\",\n    \"propertyId\": \"property_123\",\n    \"opportunityId\": \"opportunity_123\",\n    \"quoteTypeId\": \"quote_type_123\",\n    \"quoteTemplateId\": \"quote_template_123\",\n    \"name\": \"8.4 kW solar proposal\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/quotes\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"customerId\": \"customer_123\",\n  \"propertyId\": \"property_123\",\n  \"opportunityId\": \"opportunity_123\",\n  \"quoteTypeId\": \"quote_type_123\",\n  \"quoteTemplateId\": \"quote_template_123\",\n  \"name\": \"8.4 kW solar proposal\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-quote","groupSlug":"quotes","navigationGroup":"Quotes","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/quotes/{id}":{"get":{"operationId":"getQuote","tags":["Quotes"],"summary":"Get one Quote","x-required-scopes":["quotes:read"],"responses":{"200":{"description":"Quote envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: quotes:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"description":"Get one Quote","parameters":[{"name":"id","in":"path","required":true,"description":"Quote identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getQuote","x-llm-guidance":"Get one Quote. Use an organization API key with quotes:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/quotes/$SOLAROS_QUOTE\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/quotes/${process.env.SOLAROS_QUOTE}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/quotes/{os.environ['SOLAROS_QUOTE']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-quote","groupSlug":"quotes","navigationGroup":"Quotes","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"patch":{"operationId":"updateDraftQuote","tags":["Quotes"],"summary":"Update editable Quote metadata and custom Fields","description":"Updates only editable DRAFT/PENDING_APPROVAL Quote metadata and customFields. Post-send Quotes are immutable through this generic PATCH, except that a request with only originatorId can correct who a Quote credits at any status. originatorId is logged as an Originator change with its own quote.updated event. ownerId and quoteTypeId are not writable here.","x-required-scopes":["quotes:write"],"responses":{"200":{"description":"Updated Quote envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation error, including an Originator who cannot be credited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: quotes:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Quote already sent, or a travel charge blocks changing it","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Quote identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for updateDraftQuote.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"name":{"type":"string"},"customerId":{"type":"string"},"propertyId":{"type":["string","null"]},"opportunityId":{"type":["string","null"]},"validUntil":{"type":["string","null"]},"summary":{"type":["string","null"]},"notes":{"type":["string","null"]},"terms":{"type":["string","null"]},"originatorId":{"type":"string","description":"Credits a different active or draft same-organization Team Member, and writes its own activity entry and updated event. An Originator cannot be cleared. Naming a deactivated Team Member is refused unless they are already the Originator."},"customFields":{"type":"object","additionalProperties":true,"description":"Field Values keyed by savedIdentity from GET /api/v1/schema."}}},"examples":{"updatedraftquoteRequest":{"value":{"name":"8.4 kW solar and storage proposal"}}}}}},"x-tool-name":"orgApi.updateDraftQuote","x-llm-guidance":"Update editable Quote metadata and custom Fields. Use an organization API key with quotes:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/quotes/$SOLAROS_QUOTE\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"name\":\"8.4 kW solar and storage proposal\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/quotes/${process.env.SOLAROS_QUOTE}`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"name\": \"8.4 kW solar and storage proposal\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/quotes/{os.environ['SOLAROS_QUOTE']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"name\": \"8.4 kW solar and storage proposal\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"update-draft-quote","groupSlug":"quotes","navigationGroup":"Quotes","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/quotes/{id}/content":{"get":{"operationId":"getQuoteBuilderContent","tags":["Quote Builder Content"],"summary":"Get purpose-built Quote builder content","description":"Returns one Quote content graph inside the organization boundary using first-party builder concepts instead of raw child models: sections and lines, pricing inputs/computed totals, solar and system design data, financing scenarios, payment schedule funding shares (paymentSchedule.fundingSources, one per party) and milestones, incentives, assumptions, savings, environmental data, and calculation status. offeredFundingSources lists what financingScenarios may be written as: Cash first, then the saved financing options this Quote offers, each with financingOptionId (null for plain Cash, when the organization has no saved Cash option), name, and type. Hourly lines expose billing=HOURLY, estimated quantity, unitPrice as the technician-hour rate, minimumHours and laborLimit as decimal strings. Their paymentSchedule has one unbilled_hours milestone, amount 0, and no funding shares, even if old deposits are stored. Required scope: quotes:content:read.","x-required-scopes":["quotes:content:read"],"responses":{"200":{"description":"Quote builder content envelope","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"required":["data","meta"],"properties":{"data":{"type":"object","additionalProperties":true,"properties":{"sections":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"lines":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"billing":{"type":"string","enum":["FIXED","HOURLY"],"readOnly":true,"description":"Explicit billing mode. Unit hour alone does not make a fixed line hourly."},"quantity":{"type":["string","null"],"description":"Estimated technician-hours when billing is HOURLY; never earned hours."},"unitPrice":{"type":["string","null"],"description":"Rate per technician-hour when billing is HOURLY."},"minimumHours":{"type":["string","null"],"readOnly":true,"description":"Project-wide minimum in quarter-hour increments."},"laborLimit":{"type":["string","null"],"readOnly":true,"description":"Authorized labor amount before tax, excluding fixed items."}}}}}}},"financingScenarios":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"prepaidProviderFundingComputed":{"type":["string","null"],"readOnly":true,"description":"A prepaid plan's provider funding in full: what the provider pays the contractor."},"prepaidPassedToCustomerInput":{"type":["string","null"],"readOnly":true,"description":"The part of a prepaid plan's provider funding passed to the customer, when less than the most the financing option allows was chosen in solarOS; null passes the most. Not writable through PATCH."},"prepaidPassedToCustomerComputed":{"type":["string","null"],"readOnly":true,"description":"The part of a prepaid plan's provider funding taken off the customer's price."},"prepaidCustomerNetUpfrontComputed":{"type":["string","null"],"readOnly":true,"description":"The price less the part of the provider's funding passed to the customer."},"quoteDisclaimerEnabled":{"type":["boolean","null"],"readOnly":true,"description":"This quote's switch for a prepaid plan's quote disclaimer; null follows the financing option."},"quoteDisclaimerOverride":{"type":["string","null"],"readOnly":true,"description":"This quote's own wording for the quote disclaimer; null uses the financing option's."},"agreementNoteEnabled":{"type":["boolean","null"],"readOnly":true,"description":"This quote's switch for a prepaid plan's agreement note; null follows the financing option."},"agreementNoteOverride":{"type":["string","null"],"readOnly":true,"description":"This quote's own wording for the agreement note; null uses the financing option's."},"isCustom":{"type":"boolean","readOnly":true,"description":"True for a loan or cash option a rep added in solarOS with their own terms, where the organization allows it. PATCH never creates one."}}}},"paymentSchedule":{"type":"object","additionalProperties":true,"description":"Hourly quotes always return one unbilled_hours milestone with amount 0 and no funding shares. The zero is a dynamic amount placeholder; the quote estimate is not payable.","properties":{"milestones":{"type":"array","items":{"type":"object","additionalProperties":true,"properties":{"type":{"type":"string"},"amount":{"type":["string","null"]}}}}}}}},"meta":{"$ref":"#/components/schemas/OrgApiMeta"}}}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing quotes:content:read scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Quote not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Quote identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getQuoteBuilderContent","x-llm-guidance":"Get purpose-built Quote builder content. Use an organization API key with quotes:content:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/quotes/$SOLAROS_QUOTE/content\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/quotes/${process.env.SOLAROS_QUOTE}/content`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/quotes/{os.environ['SOLAROS_QUOTE']}/content\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-quote-builder-content","groupSlug":"quote-builder-content","navigationGroup":"Quote Builder Content","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}},"patch":{"operationId":"patchQuoteBuilderContent","tags":["Quote Builder Content"],"summary":"Update editable Quote builder content","description":"Hourly authoring through v1 or MCP is not supported; create hourly lines in the quote builder or use a saved hourly template. Updates purpose-built builder content families while the Quote is editable: sections and lines, pricing adjustments, solar/system design, financing scenarios, payment schedule milestones, incentives, assumptions, savings, and environmental data. Each supplied array replaces that entire content family; omit a family to leave it unchanged. Each financingScenarios entry must be one of the Quote's offeredFundingSources (see GET): send its financingOptionId with the same type. The saved option's terms are copied and any term you send overrides them. A loan's aprInput must be within the lender's saved APR range and its downPaymentInput at least the lender's minimum, and exactly one entry must have isDefault true: the funding source on the proposal (400 VALIDATION_FAILED). Changed 2026-10: custom terms (an entry with no financingOptionId) and options the Quote does not offer used to be stored and are now refused with 400 FUNDING_SOURCE_NOT_OFFERED; error.details.issues names each entry and why, and nothing is written. To migrate, sell the customer's own loan as Cash, or save the lender as a financing option in solarOS and turn it on for the Quote family: Quotes created after that offer it; GET offeredFundingSources shows whether an existing Quote does (a Quote created in solarOS keeps the list it was created with). Plain Cash with no financingOptionId is accepted only when the organization has no saved Cash option. To keep financing the Quote no longer offers, omit financingScenarios. Replacing sections that contain a managed travel charge returns 409. Frozen travel pricing cannot be edited; use the quote travel controls or duplicate the quote. Battery backupPercent and estimatedBackupHours are compatibility inputs that are not persisted; responses derive them from dispatch configuration and load assumptions. No-op PATCH requests return changed=false without ActivityLog, domain event, or timestamp churn. Material writes reject customer-facing Quote states, validate builder constraints such as solar-only system design, and emit ActivityLog plus quote.content.updated domain events with changedFields for webhook consumers. An accepted Quote returns 409 QUOTE_DESIGN_LOCKED: its design, usage, pricing and calculation are what was sold, and changes after the sale go through a change order on the project. Changed 2026-10: accepted Quotes returned 409 CONFLICT before; other customer-facing states still do. Required scope: quotes:content:write.","x-required-scopes":["quotes:content:write"],"responses":{"200":{"description":"Updated Quote builder content envelope with changed metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"400":{"description":"Validation or builder constraint error, or FUNDING_SOURCE_NOT_OFFERED when a financingScenarios entry is custom terms or an option the Quote does not offer","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing quotes:content:write scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Quote not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"QUOTE_DESIGN_LOCKED when the Quote was accepted; otherwise the Quote requires revision/duplicate flow, managed travel prevents section replacement, or array replacement would overwrite hand-edited design rows (HAND_EDITED_ROW); reconcile edits before explicitly confirming with solar.force","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Quote identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for patchQuoteBuilderContent.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"sections":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"description":{"type":["string","null"]},"sortOrder":{"type":"integer"},"isCollapsed":{"type":"boolean"},"showLineItems":{"type":"boolean"},"isVisibleToCustomer":{"type":"boolean"},"showLinesToCustomer":{"type":"boolean"},"customerDisplayName":{"type":["string","null"]},"lines":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["name"],"properties":{"name":{"type":"string"},"description":{"type":["string","null"]},"productId":{"type":["string","null"]},"quantity":{"type":"number"},"unit":{"type":"string"},"unitPrice":{"type":"number"},"unitCost":{"type":["number","null"]},"discountType":{"type":["string","null"],"enum":["PERCENTAGE","FIXED",null]},"discountValue":{"type":["number","null"]},"isOptional":{"type":"boolean"},"isSelected":{"type":"boolean"},"isTaxable":{"type":"boolean"},"isVisibleToCustomer":{"type":"boolean"},"showPriceToCustomer":{"type":"boolean"},"customerDisplayName":{"type":["string","null"]},"specs":{},"templateLineKey":{"type":["string","null"]}}}}}},"description":"Replaces all sections. Returns 409 when a generated travel charge owns a line; omit this family to retain that decision."},"pricing":{"type":"object","additionalProperties":false,"properties":{"methodology":{"type":"string","enum":["ppw","cost_plus","package","tiered"]},"tierId":{"type":["string","null"]},"pricePerWattInput":{"type":["number","null"]},"packagePriceInput":{"type":["number","null"]},"equipmentCostInput":{"type":"number"},"laborCostInput":{"type":"number"},"permitFeesInput":{"type":"number"},"overheadInput":{"type":"number"},"marginPercentInput":{"type":["number","null"]},"marginAmountInput":{"type":["number","null"]},"taxRateInput":{"type":["number","null"]},"overrides":{}}},"solar":{"type":"object","additionalProperties":false,"properties":{"systemSizeKw":{"type":["number","null"]},"annualProductionKwh":{"type":["number","null"]},"panelCount":{"type":["integer","null"],"description":"Stands only on a Quote with no panels on its arrays. On a Quote that has them, the Quote's next calculation replaces it with the arrays' total."},"inverterType":{"type":["string","null"]},"utilityCompany":{"type":["string","null"]},"preSolarAnnualBillUsd":{"type":["number","null"]},"preSolarAnnualKwh":{"type":["number","null"]},"postSolarAnnualBillUsd":{"type":["number","null"]},"projectedSavingsYear1":{"type":["number","null"],"description":"Set by the Quote's calculation from its bill comparison: a value written here is replaced when the Quote is next calculated."},"solarOffsetPercent":{"type":["number","null"]},"roofTypeId":{"type":["string","null"]},"orgRoofTypeConfigId":{"type":["string","null"]},"roofAgeYears":{"type":["integer","null"]},"siteNotes":{"type":["string","null"]},"siteLat":{"type":["number","null"]},"siteLng":{"type":["number","null"]},"details":{},"rateScheduleId":{"type":["string","null"],"description":"The home's utility rate schedule today: the platform's or one of the organization's own. A generation supplier's schedule (one of a Community Choice Aggregator's, which prices generation alone) is refused with 400 VALIDATION_FAILED (details.issues path solar.rateScheduleId): choose the utility's schedule and set the supplier with generationProviderId."},"postSolarRateScheduleId":{"type":["string","null"],"description":"The rate schedule the home moves to with solar; null uses the one today's schedule names. The same rules as rateScheduleId: a generation supplier's schedule is refused with 400 VALIDATION_FAILED (details.issues path solar.postSolarRateScheduleId)."},"baselineOverrideKwh":{"type":["number","null"]},"baselineTerritory":{"type":["string","null"],"description":"The home's baseline territory, the code printed on its utility bill (PG&E uses a letter, e.g. X). Matched in any case to the territories of the utilities the Quote's rates bill from (today's, after solar, and the one today's moves solar customers to) and stored as the utility spells it. A code they don't have, or any code when none has a baseline table on file, is refused with 400 VALIDATION_FAILED (details.issues path solar.baselineTerritory); a Quote with no rate yet is checked against every table on file, and a value sent back unchanged is kept. Rates that bill a baseline allowance, such as PG&E E-1 and E-TOU-C, need it; null uses the organization's default. Without either, the solar calculation reports MISSING_BASELINE_TERRITORY."},"baselineAllElectric":{"type":"boolean","description":"True when electric heat is the home's main heat source: it gets the larger all-electric baseline allowance."},"generationProviderId":{"type":["string","null"],"description":"The Community Choice Aggregator the home buys its power from, such as Sonoma Clean Power, when the utility bill names one under Electric Generation Charges. Null, the default, means the utility supplies it. The calculation then bills the utility's delivery charges, the Power Charge Indifference Adjustment (PCIA) and franchise fee surcharge for the home's vintage, and the supplier's generation rates, and credits exports in each one's own way. It needs pciaVintage, and must bill through the utility of the Quote's rates, before and after solar. A supplier the organization can't see, one billing through another utility, or a rate change that would leave it on another utility's rate is refused with 400 VALIDATION_FAILED (details.issues path solar.generationProviderId). Null clears pciaVintage and generationProductKey too."},"pciaVintage":{"type":["integer","null"],"description":"The home's PCIA vintage: the year on its PG&E bill beside the Power Charge Indifference Adjustment. It sets that charge and the franchise fee surcharge. Required with generationProviderId; a year the utility has no PCIA rate for, or a year sent with no supplier, is refused with 400 VALIDATION_FAILED (details.issues path solar.pciaVintage)."},"generationProductKey":{"type":["string","null"],"description":"The supplier's premium product the home buys, such as evergreen for Sonoma Clean Power EverGreen. Null is its standard product. A key the supplier doesn't offer, or one sent with no supplier, is refused with 400 VALIDATION_FAILED (details.issues path solar.generationProductKey). Changing generationProviderId without it drops it."},"arrays":{"type":"array","description":"Replaces all arrays on the Quote. Refused with 409 when an existing design-managed array row was hand-edited in the builder, unless solar.force is true.","items":{"type":"object","additionalProperties":false,"required":["panelCount","panelWattage"],"properties":{"name":{"type":["string","null"]},"panelCount":{"type":"integer"},"panelWattage":{"type":"number"},"azimuth":{"type":["number","null"]},"tilt":{"type":["number","null"]},"shadingFactor":{"type":["number","null"]},"soilingFactor":{"type":["number","null"]},"snowLossFactor":{"type":["number","null"]},"arraySizeKw":{"type":["number","null"]},"annualProductionKwh":{"type":["number","null"]},"grossAnnualKwh":{"type":["number","null"]},"productionProfile":{},"panelProductId":{"type":["string","null"]},"details":{},"sortOrder":{"type":"integer"}}}},"inverters":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["type"],"properties":{"type":{"type":"string","enum":["string","micro","hybrid","other"]},"manufacturer":{"type":["string","null"]},"model":{"type":["string","null"]},"quantity":{"type":"integer"},"powerKw":{"type":["number","null"]},"productId":{"type":["string","null"]},"sortOrder":{"type":"integer"}}}},"batteries":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["capacityKwh"],"properties":{"manufacturer":{"type":["string","null"]},"model":{"type":["string","null"]},"capacityKwh":{"type":"number"},"powerKw":{"type":["number","null"]},"quantity":{"type":"integer"},"backupPercent":{"type":["number","null"],"description":"Compatibility input only. The value is not persisted; responses derive it from the Quote battery dispatch configuration."},"estimatedBackupHours":{"type":["number","null"],"description":"Compatibility input only. The value is not persisted; responses calculate runtime from capacity, reserve, and load assumptions."},"productId":{"type":["string","null"]},"details":{"description":"Free-form row details. details.unitRole is EXPANSION for an expansion unit (absent or MAIN for a main unit). details.onSite true marks the battery already at the home that an expansion-only sale adds to: it counts toward the bank's power, backup hours and expansion limit, but it is not sold — not priced, not on the proposal and not in the sold system."},"sortOrder":{"type":"integer"}}}},"systemDesign":{"type":"object","additionalProperties":false,"properties":{"designMode":{"type":"string","enum":["auto","manual","hybrid"]},"activePanels":{"deprecated":true,"readOnly":true,"description":"Retired Google-layout input. Accepted for compatibility but ignored on writes; reads preserve the stored value. Author panels in customRoofSegments."},"obstructions":{},"setbacks":{},"targetOffsetPercent":{"type":["number","null"]},"selectedPanelProduct":{"type":["string","null"]},"totalActivePanels":{"type":["integer","null"]},"designSizeKw":{"type":["number","null"]},"estimatedProductionKwh":{"type":["number","null"]},"customRoofSegments":{},"canvasImageBounds":{}}},"force":{"type":"boolean","description":"Confirms overwriting hand-edited, design-managed array rows when replacing arrays. Without it, such a replacement is refused with 409 HAND_EDITED_ROW. Never stored."}}},"financingScenarios":{"type":"array","description":"Replaces all financing on the Quote. Each entry must be one of the Quote's offeredFundingSources from GET /quotes/{id}/content, and takes the saved option's terms unless it sends its own; custom terms and options the Quote does not offer return 400 FUNDING_SOURCE_NOT_OFFERED. Exactly one entry has isDefault true.","items":{"type":"object","additionalProperties":false,"required":["type","name"],"properties":{"financingOptionId":{"type":["string","null"],"description":"A saved financing option the Quote offers. Null only for plain Cash, when the organization has no saved Cash option."},"type":{"type":"string","enum":["CASH","LOAN","LEASE","PPA","PREPAID_TPO"],"description":"Must match the saved financing option type."},"name":{"type":"string"},"dealerFeePercentInput":{"type":["number","null"]},"dealerFeeTreatmentInput":{"type":"string","enum":["ADD_ON_TOP","ABSORBED"]},"loanTermMonthsInput":{"type":["integer","null"]},"aprInput":{"type":["number","null"],"description":"A loan's APR, within the lender's saved range."},"downPaymentInput":{"type":["number","null"],"description":"A loan's cash down, at least the lender's minimum. Starts at that minimum."},"leaseTermYearsInput":{"type":["integer","null"]},"leaseEscalatorPercentInput":{"type":["number","null"]},"ppaTermYearsInput":{"type":["integer","null"]},"ppaRatePerKwhInput":{"type":["number","null"]},"ppaEscalatorPercentInput":{"type":["number","null"]},"prepaidProviderFundingInput":{"type":["number","null"],"description":"A prepaid plan's provider funding. The customer's price comes down by at most the share of it the saved option passes on (a percent of the price), the rest staying the contractor's."},"prepaidTpoFramingInput":{"type":["string","null"],"enum":["PREPAID_PPA","PREPAID_LEASE",null]},"cashDiscountPercentInput":{"type":["number","null"],"description":"A cash plan's discount, as a percent of the price. On a solar Quote it comes off the Quote's total at its next calculation, with discountAmount and the milestone amounts following."},"isDefault":{"type":"boolean","description":"The funding source on the proposal. Exactly one entry is."}}}},"paymentSchedule":{"type":"object","additionalProperties":false,"properties":{"fundingSources":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["name","inputValue"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"type":{"type":"string","enum":["cash","financed","other"]},"inputType":{"type":"string","enum":["fixed","percent","remainder"]},"inputValue":{"type":"number"},"sortOrder":{"type":"integer"}}}},"milestones":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["name","type","inputValue"],"properties":{"name":{"type":"string"},"type":{"type":"string","enum":["percent_of_total","percent_of_source_pool","percent_of_remaining","fixed"]},"inputValue":{"type":"number"},"fundingSourceId":{"type":["string","null"]},"capAmount":{"type":["number","null"]},"dueUponCategory":{"type":["string","null"],"enum":["DEPOSIT","DEPOSIT_SOLAR","CUSTOMER_PLAN_APPROVAL","SUBSTANTIAL_COMPLETION_OF_SOLAR_WORK","FINAL_SOLAR_PERMIT_RECEIVED","PTO_RECEIVED","OTHER",null]},"dueOnEvent":{"type":["string","null"]},"sortOrder":{"type":"integer"}}}}}},"incentives":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["type","name","valueType","value"],"properties":{"type":{"type":"string","enum":["FEDERAL_TAX_CREDIT","STATE_TAX_CREDIT","UTILITY_REBATE","STATE_REBATE","SREC","LOCAL_INCENTIVE","OTHER"]},"name":{"type":"string"},"valueType":{"type":"string","enum":["PERCENT","FLAT"]},"value":{"type":"number"},"amountComputed":{"type":"number"},"isCustomerFacing":{"type":"boolean"},"notes":{"type":["string","null"]}}}},"assumptions":{"type":"object","additionalProperties":false,"properties":{"degradationRatePercent":{"type":"number"},"systemLifetimeYears":{"type":"integer"},"performanceRatio":{"type":"number"},"utilityEscalationPercent":{"type":["number","null"]},"netMeteringPolicy":{"type":["string","null"]},"discountRatePercent":{"type":["number","null"]},"inflationRatePercent":{"type":["number","null"]},"inverterReplacementYear":{"type":["integer","null"]},"inverterReplacementCost":{"type":["number","null"]},"gridEmissionsFactor":{"type":["number","null"]},"overrides":{}}},"savings":{"type":"object","additionalProperties":false,"properties":{"annualBillBeforeComputed":{"type":"number"},"monthlyBillBeforeComputed":{"type":"number"},"annualBillAfterComputed":{"type":"number"},"monthlyBillAfterComputed":{"type":"number"},"monthlyBillsBeforeComputed":{},"monthlyBillsAfterComputed":{},"annualSavingsYear1Computed":{"type":"number"},"lifetimeSavingsComputed":{"type":"number"},"lifetimeSavingsNetComputed":{"type":"number"},"savingsByScenarioComputed":{},"paybackYearsComputed":{"type":["number","null"]},"roiPercentComputed":{"type":["number","null"]},"paybackByScenarioComputed":{},"yearlyProjectionComputed":{},"assumptionsSnapshot":{}}},"environmental":{"type":"object","additionalProperties":false,"properties":{"co2OffsetLbsComputed":{"type":"number"},"co2OffsetTonsComputed":{"type":"number"},"treesEquivalentComputed":{"type":"number"},"carsOffRoadComputed":{"type":"number"},"milesDrivenComputed":{"type":"number"},"homesEquivalentComputed":{"type":"number"},"annualCo2OffsetLbsComputed":{"type":"number"},"annualTreesEquivalentComputed":{"type":"number"},"gridEmissionsFactorUsed":{"type":["number","null"]}}}}},"examples":{"patchquotebuildercontentRequest":{"value":{"sections":[{"name":"Solar installation","lines":[{"name":"PV installation","quantity":1,"unit":"each","unitPrice":31500}]}],"solar":{"systemSizeKw":8.4,"arrays":[{"panelCount":21,"panelWattage":400}],"batteries":[{"manufacturer":"Example Energy","capacityKwh":13.5,"quantity":1}],"systemDesign":{"designMode":"manual","totalActivePanels":21,"designSizeKw":8.4}}}}}}}},"x-tool-name":"orgApi.patchQuoteBuilderContent","x-llm-guidance":"Update editable Quote builder content. Use an organization API key with quotes:content:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X PATCH \"$SOLAROS_BASE_URL/api/v1/quotes/$SOLAROS_QUOTE/content\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  --data '{\"sections\":[{\"name\":\"Solar installation\",\"lines\":[{\"name\":\"PV installation\",\"quantity\":1,\"unit\":\"each\",\"unitPrice\":31500}]}],\"solar\":{\"systemSizeKw\":8.4,\"arrays\":[{\"panelCount\":21,\"panelWattage\":400}],\"batteries\":[{\"manufacturer\":\"Example Energy\",\"capacityKwh\":13.5,\"quantity\":1}],\"systemDesign\":{\"designMode\":\"manual\",\"totalActivePanels\":21,\"designSizeKw\":8.4}}}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/quotes/${process.env.SOLAROS_QUOTE}/content`, {\n  method: 'PATCH',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n  },\n  body: JSON.stringify({\n    \"sections\": [\n      {\n        \"name\": \"Solar installation\",\n        \"lines\": [\n          {\n            \"name\": \"PV installation\",\n            \"quantity\": 1,\n            \"unit\": \"each\",\n            \"unitPrice\": 31500\n          }\n        ]\n      }\n    ],\n    \"solar\": {\n      \"systemSizeKw\": 8.4,\n      \"arrays\": [\n        {\n          \"panelCount\": 21,\n          \"panelWattage\": 400\n        }\n      ],\n      \"batteries\": [\n        {\n          \"manufacturer\": \"Example Energy\",\n          \"capacityKwh\": 13.5,\n          \"quantity\": 1\n        }\n      ],\n      \"systemDesign\": {\n        \"designMode\": \"manual\",\n        \"totalActivePanels\": 21,\n        \"designSizeKw\": 8.4\n      }\n    }\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"PATCH\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/quotes/{os.environ['SOLAROS_QUOTE']}/content\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n    },\n    json=json.loads(\"\"\"{\n  \"sections\": [\n    {\n      \"name\": \"Solar installation\",\n      \"lines\": [\n        {\n          \"name\": \"PV installation\",\n          \"quantity\": 1,\n          \"unit\": \"each\",\n          \"unitPrice\": 31500\n        }\n      ]\n    }\n  ],\n  \"solar\": {\n    \"systemSizeKw\": 8.4,\n    \"arrays\": [\n      {\n        \"panelCount\": 21,\n        \"panelWattage\": 400\n      }\n    ],\n    \"batteries\": [\n      {\n        \"manufacturer\": \"Example Energy\",\n        \"capacityKwh\": 13.5,\n        \"quantity\": 1\n      }\n    ],\n    \"systemDesign\": {\n      \"designMode\": \"manual\",\n      \"totalActivePanels\": 21,\n      \"designSizeKw\": 8.4\n    }\n  }\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"patch-quote-builder-content","groupSlug":"quote-builder-content","navigationGroup":"Quote Builder Content","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/quotes/{id}/content/calculate":{"post":{"operationId":"calculateQuoteBuilderContent","tags":["Quote Builder Content"],"summary":"Run Quote builder content calculations","description":"Runs the app-equivalent calculation action for Quote builder content. The optional body accepts scope (all, pricing, solar, financing, payment_schedule, savings, or environmental) and force. Solar Quote Types use the solar calculation pipeline; service/general Quote Types use the general pricing pipeline. Requires Idempotency-Key and returns action.confirmed plus action.confirmationSignal so agents can verify the calculation completed before proceeding. A calculation that could not price part of the Quote finishes partial and lists why in result.errors, each with a code — for example MISSING_BASELINE_TERRITORY when the rate bills a baseline allowance and neither the Quote (solar.baselineTerritory) nor the organization names a baseline territory. A Quote for a home that buys generation from a Community Choice Aggregator (solar.generationProviderId) can also report MISSING_PCIA_VINTAGE when its vintage has no PCIA rate on file, NO_GENERATION_RATES when the supplier has no rates for the Quote's rate schedule and vintage, NO_UNBUNDLING when that rate has no generation credits on file, and NO_DELIVERY_EXPORT_VALUES when the rate after solar has no Solar Billing Plan export values for it. Each calculation of a draft re-estimates the year its interconnection application will be filed, so a draft's savings can change when that expected year rolls over. A year set in the solarOS Quote builder is kept until the calendar passes it. An accepted Quote returns 409 QUOTE_DESIGN_LOCKED: its figures are what was sold (409 CONFLICT before 2026-10). Side effects include ActivityLog, quote.content.calculated domain event, idempotency capture, and usage telemetry. Required scope: quotes:calculate.","x-required-scopes":["quotes:calculate"],"x-idempotency-key":"required","responses":{"200":{"description":"Calculation action envelope with confirmationSignal","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"400":{"description":"Validation or idempotency error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing quotes:calculate scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Quote not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Idempotency conflict, QUOTE_DESIGN_LOCKED when the Quote was accepted, or another customer-facing Quote state","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Quote identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":false,"description":"JSON request payload for calculateQuoteBuilderContent.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"scope":{"type":"string","enum":["all","pricing","solar","financing","payment_schedule","savings","environmental"]},"force":{"type":"boolean"}}},"examples":{"calculatequotebuildercontentRequest":{"value":{"scope":"all","force":false}}}}}},"x-tool-name":"orgApi.calculateQuoteBuilderContent","x-llm-guidance":"Run Quote builder content calculations. Use an organization API key with quotes:calculate. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/quotes/$SOLAROS_QUOTE/content/calculate\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"scope\":\"all\",\"force\":false}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/quotes/${process.env.SOLAROS_QUOTE}/content/calculate`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"scope\": \"all\",\n    \"force\": false\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/quotes/{os.environ['SOLAROS_QUOTE']}/content/calculate\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"scope\": \"all\",\n  \"force\": false\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"calculate-quote-builder-content","groupSlug":"quote-builder-content","navigationGroup":"Quote Builder Content","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/quotes/{id}/aurora-sync":{"post":{"operationId":"requestQuoteAuroraSync","tags":["Quote Actions"],"summary":"Request Aurora sync for a Quote","description":"Requests Aurora sync work for one Quote. Requires Idempotency-Key. The request may provide auroraDesignId and auroraProjectId directly, or the action resolves them: the Quote's Aurora design link (solarOS stores its project beside it, and skips links into an Aurora account the organization no longer connects), else the design the Quote last imported, else the Quote's or its Property's project. The sync request is recorded first — ActivityLog, the quote.aurora_sync_requested domain event and the Idempotency-Key — so it stands whatever the import does, and a client retrying on a timeout gets the recorded request back instead of a second import (designImport { status: in_progress } while the first request is still importing). When the organization has connected Aurora in solarOS, the action then imports the design into the Quote with the organization's default import parts — the same import the solarOS Quote builder runs: arrays, inverters, batteries, battery mode, the design picture and Aurora's production, plus usage and rate plans when the default includes usage, Aurora's system price (as the Quote's fixed price, with Aurora's adders and discounts as adjustment lines) when it includes price, and the plan selected in Aurora's sales mode (matched to the organization's financing options by name) when it includes financing — and reports it in designImport: { status: imported | unchanged, revision, parts, notes } or { status: skipped | failed, reason, message, notes }; notes are what a person should check on the Quote ({ code, message, part }). The import never replaces a person's work or guesses: it is skipped, writing nothing, when a part it would replace was edited in solarOS since the last import (EDITED_IN_SOLAROS), when Aurora marks the design's production out of date (PRODUCTION_NOT_CURRENT), when Aurora prices a battery the design does not have (BATTERY_PRICED_NOT_DESIGNED), when the design is for another address than the Quote's property (ADDRESS_MISMATCH), when a rate plan matches only loosely (RATE_PLAN_UNCERTAIN), when Aurora's price is under the organization's price-per-watt floor (PRICE_BELOW_FLOOR), when a module or battery has no matching product (EQUIPMENT_UNMATCHED), when Aurora has no production for the design (BLOCKED), without quotes:content:write (CONTENT_WRITE_SCOPE_REQUIRED), for a Quote past DRAFT or PENDING_APPROVAL (QUOTE_NOT_EDITABLE), and when Aurora is not connected (AURORA_NOT_CONNECTED). Aurora not answering, or any other failure, reports failed (AURORA_UNAVAILABLE and the like, IMPORT_FAILED). The same design revision imported again is unchanged. Side effects include ActivityLog, quote.aurora_sync_requested domain event, idempotency capture, usage telemetry, and for an import the Quote's solar content, load profile, pricing, financing scenarios and a recalculation. Required scope: quotes:write.","x-required-scopes":["quotes:write"],"x-idempotency-key":"required","responses":{"200":{"description":"Aurora sync request action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"400":{"description":"Validation, idempotency, or missing Aurora identifiers","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing quotes:write scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Quote not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Quote identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":false,"description":"JSON request payload for requestQuoteAuroraSync.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"auroraDesignId":{"type":"string"},"auroraProjectId":{"type":"string"}}},"examples":{"requestquoteaurorasyncRequest":{"value":{"auroraDesignId":"aurora_design_123","auroraProjectId":"aurora_project_456"}}}}}},"x-tool-name":"orgApi.requestQuoteAuroraSync","x-llm-guidance":"Request Aurora sync for a Quote. Use an organization API key with quotes:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/quotes/$SOLAROS_QUOTE/aurora-sync\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"auroraDesignId\":\"aurora_design_123\",\"auroraProjectId\":\"aurora_project_456\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/quotes/${process.env.SOLAROS_QUOTE}/aurora-sync`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"auroraDesignId\": \"aurora_design_123\",\n    \"auroraProjectId\": \"aurora_project_456\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/quotes/{os.environ['SOLAROS_QUOTE']}/aurora-sync\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"auroraDesignId\": \"aurora_design_123\",\n  \"auroraProjectId\": \"aurora_project_456\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"request-quote-aurora-sync","groupSlug":"quote-actions","navigationGroup":"Quote Actions","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/quotes/{id}/send":{"post":{"operationId":"sendQuote","tags":["Quote Actions"],"summary":"Send a draft Quote through solarOS","description":"Sends the Quote using its configured customer delivery path. A service quote on a prepaid plan with no provider funding entered returns 409 CONFLICT with reason PREPAID_FUNDING_MISSING; the quote remains unsent. Hourly quotes return 400 VALIDATION_FAILED for invalid hourly terms, financing, a discount above the fixed-item total, or a legacy sourceProjectId add-work-order link; the quote remains unsent. Hourly quotes must use their own project or an explicit accepted parent-quote link. The optional body accepts additionalMessage; recipientEmail and message are not writable fields. A solar Quote is not sent while its calculations are running (409 CONFLICT, details.reason SOLAR_CALCULATIONS_RUNNING) or did not finish (SOLAR_CALCULATIONS_NOT_CURRENT — run POST /quotes/{id}/content/calculate first; when the last run stopped on a problem the client can fix, such as MISSING_BASELINE_TERRITORY, details.calculationErrors lists each { code, message } to fix before recalculating). A solar Quote with designed panels is not sent while its system has no base price (SOLAR_BASE_PRICE_MISSING) or while its saved base price per watt is below the price-list floor for the system size and no one confirmed it in solarOS (SOLAR_PRICE_BELOW_FLOOR). An API key cannot confirm a below-floor price. A solar Quote whose total is $0 is not sent (SOLAR_TOTAL_ZERO). A solar Quote is not sent while the plan its proposal leads with has no price (SOLAR_PLAN_NOT_PRICED): its default financing scenario is a lease or PPA with no payment, a PPA whose provider rate table has no offer for the system, or a prepaid plan with no customer share — or none of its financing scenarios has a price. Give that scenario its price (a PPA rate the provider's table offers, a prepaid plan's provider funding) or make a priced scenario the default with PATCH /quotes/{id}/content — a lease's payment is entered in solarOS — then run POST /quotes/{id}/content/calculate and send again. A solar Quote is not sent while it has more expansion batteries than its main batteries take (SOLAR_TOO_MANY_EXPANSIONS): each main battery product says how many expansions one unit takes in solarOS; remove expansions or add a main unit there, then send again. A solar Quote whose installer agreement goes out for signature by itself when the Quote is accepted is not sent while that agreement would print a value blank (AGREEMENT_VALUE_BLANK): details.blockers lists each { code, message }, the message naming the value, such as \"Customer phone would print blank on the agreement.\" A value the agreement prints only on a condition the Quote doesn't meet is not counted, nor is one the Quote leaves blank by design. Fill each value — a Quote field with PATCH /quotes/{id}/content, a customer's with PATCH /customers/{id} — and send again. A solar Quote whose agreement prints annual production is not sent while that production is a regional estimate (SOLAR_PRODUCTION_ESTIMATED): run POST /quotes/{id}/content/calculate, then send. On a solar Quote, the response lists in warnings, each { code, message }, what solarOS only warns about; the Quote is sent regardless. SOLAR_INTERCONNECTION_YEAR_PASSED: its savings assume an interconnection application filed in a year it can no longer be filed in, and the utility credits exports differently in the year it can — POST /quotes/{id}/content/calculate on a draft prices it on that year, so run it before sending. SOLAR_STARTER_TEXT: what the homeowner receives still carries the placeholder text of the starter quote setup — its terms, scope of work, warranty or a line item description — or its payment schedule is still named as that setup named it; the message names each place. Replace the terms with PATCH /quotes/{id} and line descriptions through the content API; the scope of work, the warranty and the schedule's name are changed in solarOS.","x-required-scopes":["quotes:send"],"x-idempotency-key":"required","responses":{"200":{"description":"Quote send action envelope, with warnings listing what solarOS only warns about","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: quotes:send","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"409":{"description":"Quote is not a draft, travel pricing needs review, its solar calculations are not current, its solar system price is missing, below the floor unconfirmed, or $0, the plan its proposal leads with has no price, its agreement would print a value blank, or the production its agreement prints is a lookup estimate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Quote identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":false,"description":"JSON request payload for sendQuote.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"additionalMessage":{"type":["string","null"]}}},"examples":{"sendquoteRequest":{"value":{"additionalMessage":"Here is the updated solar proposal for review."}}}}}},"x-tool-name":"orgApi.sendQuote","x-llm-guidance":"Send a draft Quote through solarOS. Use an organization API key with quotes:send. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/quotes/$SOLAROS_QUOTE/send\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"additionalMessage\":\"Here is the updated solar proposal for review.\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/quotes/${process.env.SOLAROS_QUOTE}/send`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"additionalMessage\": \"Here is the updated solar proposal for review.\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/quotes/{os.environ['SOLAROS_QUOTE']}/send\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"additionalMessage\": \"Here is the updated solar proposal for review.\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"send-quote","groupSlug":"quote-actions","navigationGroup":"Quote Actions","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/quotes/{id}/mark-accepted":{"post":{"operationId":"markQuoteAccepted","tags":["Quote Actions"],"summary":"Record external or staff-mediated Quote acceptance","description":"A service quote on a prepaid plan with no provider funding entered returns 409 CONFLICT with reason PREPAID_FUNDING_MISSING; acceptance does not occur. Hourly quotes return 400 VALIDATION_FAILED for invalid hourly terms, financing, discounts exceeding fixed items, or legacy sourceProjectId add-work-order links; acceptance does not occur. Hourly quotes use quote acceptance instead of installer agreement signing: ON_SIGNING project creation becomes ON_ACCEPTANCE, and MANUAL stays manual. Records acceptance with a required method plus optional accepter identity, notes, and downstream Project/Work Order External References. acceptedAt, acceptedBy, and source are not accepted. When the plan a solar Quote's proposal presents is a PPA or lease, the provider sends its own agreement, so a Project that would wait for the company's signed agreement starts on acceptance instead.","x-required-scopes":["quotes:accept"],"x-idempotency-key":"required","responses":{"200":{"description":"Quote acceptance action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: quotes:accept","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Quote identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for markQuoteAccepted.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["method"],"properties":{"method":{"type":"string","enum":["VERBAL","EMAIL","IN_APP","SIGNATURE"]},"acceptedByName":{"type":["string","null"]},"acceptedByEmail":{"type":["string","null"],"format":"email"},"notes":{"type":["string","null"]},"externalReferences":{"type":"object","additionalProperties":false,"properties":{"project":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}},"workOrder":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}}}},"examples":{"markquoteacceptedRequest":{"value":{"method":"SIGNATURE","acceptedByName":"Ada Lovelace","acceptedByEmail":"ada@example.com"}}}}}},"x-tool-name":"orgApi.markQuoteAccepted","x-llm-guidance":"Record external or staff-mediated Quote acceptance. Use an organization API key with quotes:accept. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/quotes/$SOLAROS_QUOTE/mark-accepted\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"method\":\"SIGNATURE\",\"acceptedByName\":\"Ada Lovelace\",\"acceptedByEmail\":\"ada@example.com\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/quotes/${process.env.SOLAROS_QUOTE}/mark-accepted`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"method\": \"SIGNATURE\",\n    \"acceptedByName\": \"Ada Lovelace\",\n    \"acceptedByEmail\": \"ada@example.com\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/quotes/{os.environ['SOLAROS_QUOTE']}/mark-accepted\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"method\": \"SIGNATURE\",\n  \"acceptedByName\": \"Ada Lovelace\",\n  \"acceptedByEmail\": \"ada@example.com\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"mark-quote-accepted","groupSlug":"quote-actions","navigationGroup":"Quote Actions","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/quotes/{id}/contracts":{"post":{"operationId":"createContractFromQuote","tags":["Contract Actions"],"summary":"Create a quote-generated Contract","description":"Creates a Contract from a Quote using templateId and one or more signers. Optional inputs are message, mergeFieldOverrides, and External References. The first customer signer's name fills customer.fullName unless mergeFieldOverrides sets that value.","x-required-scopes":["contracts:write"],"x-idempotency-key":"required","responses":{"201":{"description":"Contract create action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: contracts:write","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Quote identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":true,"description":"JSON request payload for createContractFromQuote.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["templateId","signers"],"properties":{"templateId":{"type":"string"},"signers":{"type":"array","minItems":1,"items":{"type":"object","additionalProperties":false,"required":["name","email","role"],"properties":{"name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string"},"order":{"type":"integer"}}}},"message":{"type":["string","null"]},"mergeFieldOverrides":{"type":"object","additionalProperties":{"type":"string"}},"externalReferences":{"type":"array","items":{"type":"object","additionalProperties":false,"required":["externalSystem","externalObject","externalId"],"properties":{"externalSystem":{"type":"string"},"externalObject":{"type":"string"},"externalId":{"type":"string"},"metadata":{"type":"object","additionalProperties":true}}}}}},"examples":{"createcontractfromquoteRequest":{"value":{"templateId":"contract_template_123","signers":[{"name":"Ada Lovelace","email":"ada@example.com","role":"CUSTOMER","order":0}],"message":"Please review and sign the installation contract."}}}}}},"x-tool-name":"orgApi.createContractFromQuote","x-llm-guidance":"Create a quote-generated Contract. Use an organization API key with contracts:write. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/quotes/$SOLAROS_QUOTE/contracts\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"templateId\":\"contract_template_123\",\"signers\":[{\"name\":\"Ada Lovelace\",\"email\":\"ada@example.com\",\"role\":\"CUSTOMER\",\"order\":0}],\"message\":\"Please review and sign the installation contract.\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/quotes/${process.env.SOLAROS_QUOTE}/contracts`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"templateId\": \"contract_template_123\",\n    \"signers\": [\n      {\n        \"name\": \"Ada Lovelace\",\n        \"email\": \"ada@example.com\",\n        \"role\": \"CUSTOMER\",\n        \"order\": 0\n      }\n    ],\n    \"message\": \"Please review and sign the installation contract.\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/quotes/{os.environ['SOLAROS_QUOTE']}/contracts\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"templateId\": \"contract_template_123\",\n  \"signers\": [\n    {\n      \"name\": \"Ada Lovelace\",\n      \"email\": \"ada@example.com\",\n      \"role\": \"CUSTOMER\",\n      \"order\": 0\n    }\n  ],\n  \"message\": \"Please review and sign the installation contract.\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"create-contract-from-quote","groupSlug":"contract-actions","navigationGroup":"Contract Actions","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/contracts":{"get":{"operationId":"listContracts","tags":["Contracts"],"summary":"List quote-generated Contracts","x-required-scopes":["contracts:read"],"parameters":[{"name":"limit","in":"query","required":false,"description":"Maximum records to return. Defaults to 50 and is capped at 100.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"cursor","in":"query","required":false,"description":"Opaque record cursor from the previous response meta.nextCursor value.","schema":{"type":"string"}},{"name":"sortDir","in":"query","required":false,"description":"Sort direction. Defaults to desc.","schema":{"type":"string","enum":["asc","desc"],"default":"desc"}},{"name":"status","in":"query","required":false,"description":"Filter by exact Contract status.","schema":{"type":"string","enum":["DRAFT","PENDING_SIGNATURE","PARTIALLY_SIGNED","COMPLETED","VOIDED","EXPIRED"]}},{"name":"quoteId","in":"query","required":false,"description":"Filter by source Quote id.","schema":{"type":"string"}},{"name":"customerId","in":"query","required":false,"description":"Filter by Customer id.","schema":{"type":"string"}}],"responses":{"200":{"description":"Contract list envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiListEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: contracts:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"description":"List quote-generated Contracts","x-tool-name":"orgApi.listContracts","x-llm-guidance":"List quote-generated Contracts. Use an organization API key with contracts:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/contracts\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/contracts`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/contracts\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"list-contracts","groupSlug":"contracts","navigationGroup":"Contracts","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/contracts/{id}":{"get":{"operationId":"getContract","tags":["Contracts"],"summary":"Get one quote-generated Contract","x-required-scopes":["contracts:read"],"responses":{"200":{"description":"Contract envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiResourceEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: contracts:read","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"description":"Get one quote-generated Contract","parameters":[{"name":"id","in":"path","required":true,"description":"Contract identifier returned by the Organization API.","schema":{"type":"string"}}],"x-tool-name":"orgApi.getContract","x-llm-guidance":"Get one quote-generated Contract. Use an organization API key with contracts:read. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X GET \"$SOLAROS_BASE_URL/api/v1/contracts/$SOLAROS_CONTRACT\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\""},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/contracts/${process.env.SOLAROS_CONTRACT}`, {\n  method: 'GET',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n  },\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"GET\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/contracts/{os.environ['SOLAROS_CONTRACT']}\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n    },\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"get-contract","groupSlug":"contracts","navigationGroup":"Contracts","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/contracts/{id}/send":{"post":{"operationId":"sendContract","tags":["Contract Actions"],"summary":"Send a Contract for signature","description":"Hourly quote agreements are refused before delivery (409 CONFLICT), including existing fixed agreements whose quote has become hourly. Send the public quote link for acceptance of the current hourly terms. Fixed agreements and change-order signing retain their existing behavior. Sends using deliveryMode EMAIL or HOSTED_SIGNING. The optional body may target signerId and include message.","x-required-scopes":["contracts:send"],"x-idempotency-key":"required","responses":{"200":{"description":"Contract send action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: contracts:send","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Contract identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":false,"description":"JSON request payload for sendContract.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"deliveryMode":{"type":"string","enum":["EMAIL","HOSTED_SIGNING"]},"signerId":{"type":"string"},"message":{"type":["string","null"]}}},"examples":{"sendcontractRequest":{"value":{"deliveryMode":"EMAIL","message":"Please review and sign."}}}}}},"x-tool-name":"orgApi.sendContract","x-llm-guidance":"Send a Contract for signature. Use an organization API key with contracts:send. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/contracts/$SOLAROS_CONTRACT/send\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"deliveryMode\":\"EMAIL\",\"message\":\"Please review and sign.\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/contracts/${process.env.SOLAROS_CONTRACT}/send`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"deliveryMode\": \"EMAIL\",\n    \"message\": \"Please review and sign.\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/contracts/{os.environ['SOLAROS_CONTRACT']}/send\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"deliveryMode\": \"EMAIL\",\n  \"message\": \"Please review and sign.\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"send-contract","groupSlug":"contract-actions","navigationGroup":"Contract Actions","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/contracts/{id}/remind":{"post":{"operationId":"remindContractSigner","tags":["Contract Actions"],"summary":"Request a Contract signature reminder","description":"Hourly quote agreements are refused before delivery (409 CONFLICT), including existing fixed agreements whose quote has become hourly. Send the public quote link for acceptance of the current hourly terms. Fixed agreements and change-order signing retain their existing behavior. Requests a reminder. The body is optional. Any body fields are ignored but still participate in idempotency matching; prefer an empty object.","x-required-scopes":["contracts:send"],"x-idempotency-key":"required","responses":{"200":{"description":"Contract reminder action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: contracts:send","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Contract identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":false,"description":"JSON request payload for remindContractSigner.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Optional payload is retained for idempotency matching but its fields are ignored. Prefer an empty object."},"examples":{"remindcontractsignerRequest":{"value":{}}}}}},"x-tool-name":"orgApi.remindContractSigner","x-llm-guidance":"Request a Contract signature reminder. Use an organization API key with contracts:send. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/contracts/$SOLAROS_CONTRACT/remind\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/contracts/${process.env.SOLAROS_CONTRACT}/remind`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({}),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/contracts/{os.environ['SOLAROS_CONTRACT']}/remind\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"remind-contract-signer","groupSlug":"contract-actions","navigationGroup":"Contract Actions","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/contracts/{id}/void":{"post":{"operationId":"voidContract","tags":["Contract Actions"],"summary":"Void a Contract awaiting signatures","description":"Voids the Contract. The optional body accepts reason.","x-required-scopes":["contracts:void"],"x-idempotency-key":"required","responses":{"200":{"description":"Contract void action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: contracts:void","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Contract identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":false,"description":"JSON request payload for voidContract.","content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"reason":{"type":["string","null"]}}},"examples":{"voidcontractRequest":{"value":{"reason":"Customer requested a revised contract."}}}}}},"x-tool-name":"orgApi.voidContract","x-llm-guidance":"Void a Contract awaiting signatures. Use an organization API key with contracts:void. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/contracts/$SOLAROS_CONTRACT/void\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{\"reason\":\"Customer requested a revised contract.\"}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/contracts/${process.env.SOLAROS_CONTRACT}/void`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({\n    \"reason\": \"Customer requested a revised contract.\"\n  }),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/contracts/{os.environ['SOLAROS_CONTRACT']}/void\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{\n  \"reason\": \"Customer requested a revised contract.\"\n}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"void-contract","groupSlug":"contract-actions","navigationGroup":"Contract Actions","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}},"/contracts/{id}/sync":{"post":{"operationId":"syncContractProviderStatus","tags":["Contract Actions"],"summary":"Sync Contract provider status","description":"Refreshes provider status. The body is optional. Any body fields are ignored but still participate in idempotency matching; prefer an empty object.","x-required-scopes":["contracts:sync"],"x-idempotency-key":"required","responses":{"200":{"description":"Contract sync action envelope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiActionEnvelope"}}}},"401":{"description":"Missing or invalid organization API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"402":{"description":"Organization billing access or an endpoint-specific business quota denied the request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"403":{"description":"Missing required scope: contracts:sync","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}},"429":{"description":"Rate limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrgApiError"}}}}},"parameters":[{"name":"id","in":"path","required":true,"description":"Contract identifier returned by the Organization API.","schema":{"type":"string"}}],"requestBody":{"required":false,"description":"JSON request payload for syncContractProviderStatus.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"description":"Optional payload is retained for idempotency matching but its fields are ignored. Prefer an empty object."},"examples":{"synccontractproviderstatusRequest":{"value":{}}}}}},"x-tool-name":"orgApi.syncContractProviderStatus","x-llm-guidance":"Sync Contract provider status. Use an organization API key with contracts:sync. Check the response envelope and meta.requestId before triggering dependent workflow steps.","x-code-samples":[{"language":"curl","label":"curl","source":"curl -X POST \"$SOLAROS_BASE_URL/api/v1/contracts/$SOLAROS_CONTRACT/sync\" \\\n  -H \"Authorization: Bearer $SOLAROS_API_KEY\" \\\n  -H \"Content-Type: application/json\" \\\n  -H \"Idempotency-Key: $SOLAROS_IDEMPOTENCY_KEY\" \\\n  --data '{}'"},{"language":"typescript","label":"TypeScript","source":"const response = await fetch(`${process.env.SOLAROS_BASE_URL}/api/v1/contracts/${process.env.SOLAROS_CONTRACT}/sync`, {\n  method: 'POST',\n  headers: {\n    Authorization: `Bearer ${process.env.SOLAROS_API_KEY}`,\n    'Content-Type': 'application/json',\n    'Idempotency-Key': crypto.randomUUID(),\n  },\n  body: JSON.stringify({}),\n});\nconst result = await response.json();"},{"language":"python","label":"Python","source":"import os\nimport json\nimport uuid\nimport requests\n\nresponse = requests.request(\n    \"POST\",\n    f\"{os.environ['SOLAROS_BASE_URL']}/api/v1/contracts/{os.environ['SOLAROS_CONTRACT']}/sync\",\n    headers={\n        \"Authorization\": f\"Bearer {os.environ['SOLAROS_API_KEY']}\",\n        \"Content-Type\": \"application/json\",\n        \"Idempotency-Key\": str(uuid.uuid4()),\n    },\n    json=json.loads(\"\"\"{}\"\"\"),\n)\nresult = response.json()"}],"x-docs":{"section":"api-reference","slug":"sync-contract-provider-status","groupSlug":"contract-actions","navigationGroup":"Contract Actions","sampleCoverage":"static-complete","coverageDepth":"deep","examplesMode":"static"}}}}}