{"openapi":"3.1.0","info":{"title":"Asteri Public API","version":"2026-03-23.preview","description":"Preview OpenAPI document generated from the Asteri public contract source. This spec is derived from the same resource definitions used by the developer portal."},"servers":[{"url":"/","description":"Current application origin"}],"tags":[{"name":"Customers","description":"Customer identity, contact channels, service history, and organization-scoped records."},{"name":"Appointments","description":"Scheduling lifecycle, assignment state, completion events, and operational context."},{"name":"Estimates","description":"Quote creation, revision, sending, and approval lifecycle for service revenue flows."},{"name":"Invoices","description":"Billing state, payment readiness, and accounting-system handoff."},{"name":"Payments","description":"Collected payments, invoice linkage, payment methods, and collection-state visibility."},{"name":"Services","description":"Service catalog visibility for pricing, duration, and booking-facing configuration."},{"name":"Files","description":"Uploaded file records, MIME metadata, processing status, and storage-bucket context."},{"name":"Webhook Events","description":"Signed event delivery with retries, delivery history, secret rotation, and replay-oriented operations."}],"paths":{"/api/public/v1/customers":{"get":{"operationId":"customers-list","tags":["Customers"],"summary":"List customers in the active organization with filtering and pagination.","description":"List customers in the active organization with filtering and pagination. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerListResponse"},"example":{"data":[{"id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","organization_id":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d","account_type":"business","display_name":"North Harbor Facilities","email":"ops@northerborfacilities.com","phone":"+1-404-555-0128","created_at":"2026-03-18T15:40:12.000Z"}],"pagination":{"count":2,"limit":25,"next_cursor":null}}}}},"400":{"description":"Missing or invalid organization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["read:customers"]},"post":{"operationId":"customers-create","tags":["Customers"],"summary":"Create a customer with organization-scoped identity and contact data.","description":"Create a customer with organization-scoped identity and contact data. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomerRequest"},"example":{"account_type":"business","display_name":"North Harbor Facilities","company_name":"North Harbor Facilities","first_name":"Nora","last_name":"Harbor","email":"ops@northerborfacilities.com","phone":"+1-404-555-0128"}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomerResponse"},"example":{"data":{"id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","organization_id":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d","account_type":"business","display_name":"North Harbor Facilities","email":"ops@northerborfacilities.com","phone":"+1-404-555-0128","created_at":"2026-03-18T15:40:12.000Z"}}}}},"201":{"description":"Created response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCustomerResponse"},"example":{"data":{"id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","organization_id":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d","account_type":"business","display_name":"North Harbor Facilities","email":"ops@northerborfacilities.com","phone":"+1-404-555-0128","created_at":"2026-03-18T15:40:12.000Z"}}}}},"400":{"description":"Missing organization context or invalid request payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"409":{"description":"Duplicate customer email or conflicting customer state.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConflictErrorResponse"},"example":{"error":"Customer email already exists in this organization","field":"email"}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["write:customers"]}},"/api/public/v1/customers/{customerId}":{"get":{"operationId":"customers-get","tags":["Customers"],"summary":"Retrieve one customer and related profile metadata.","description":"Retrieve one customer and related profile metadata. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CustomerResponse"},"example":{"data":{"id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","organization_id":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d","account_type":"business","display_name":"North Harbor Facilities","email":"ops@northerborfacilities.com","phone":"+1-404-555-0128","created_at":"2026-03-18T15:40:12.000Z"}}}}},"400":{"description":"Missing or invalid organization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"404":{"description":"Requested customer record was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundErrorResponse"},"example":{"error":"Customer not found"}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["read:customers"]}},"/api/public/v1/appointments":{"get":{"operationId":"appointments-list","tags":["Appointments"],"summary":"List appointments by date range, status, customer, or technician.","description":"List appointments by date range, status, customer, or technician. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentListResponse"},"example":{"data":[{"id":"10bdff89-2f4f-4f06-8595-5f971ca0119a","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"confirmed","scheduled_start":"2026-03-24T13:00:00.000Z","scheduled_end":"2026-03-24T15:00:00.000Z","assigned_team_member_ids":["95cb6a1e-3792-451a-b905-011946edc191"]}],"pagination":{"count":2,"limit":25,"next_cursor":null}}}}},"400":{"description":"Missing or invalid organization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["read:appointments"]},"post":{"operationId":"appointments-create","tags":["Appointments"],"summary":"Create a scheduled appointment with service, technician, and timing context.","description":"Create a scheduled appointment with service, technician, and timing context. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentUpsertRequest"},"example":{"customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","scheduled_start":"2026-03-24T13:00:00.000Z","scheduled_end":"2026-03-24T15:00:00.000Z","assigned_team_member_ids":["95cb6a1e-3792-451a-b905-011946edc191"]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppointmentResponse"},"example":{"data":{"id":"10bdff89-2f4f-4f06-8595-5f971ca0119a","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"confirmed","scheduled_start":"2026-03-24T13:00:00.000Z","scheduled_end":"2026-03-24T15:00:00.000Z","assigned_team_member_ids":["95cb6a1e-3792-451a-b905-011946edc191"]}}}}},"201":{"description":"Created response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAppointmentResponse"},"example":{"data":{"id":"10bdff89-2f4f-4f06-8595-5f971ca0119a","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"confirmed","scheduled_start":"2026-03-24T13:00:00.000Z","scheduled_end":"2026-03-24T15:00:00.000Z","assigned_team_member_ids":["95cb6a1e-3792-451a-b905-011946edc191"]}}}}},"400":{"description":"Missing organization context or invalid request payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["write:appointments"]}},"/api/public/v1/appointments/{appointmentId}":{"get":{"operationId":"appointments-get","tags":["Appointments"],"summary":"Retrieve one appointment and assignment state.","description":"Retrieve one appointment and assignment state. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentResponse"},"example":{"data":{"id":"10bdff89-2f4f-4f06-8595-5f971ca0119a","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"confirmed","scheduled_start":"2026-03-24T13:00:00.000Z","scheduled_end":"2026-03-24T15:00:00.000Z","assigned_team_member_ids":["95cb6a1e-3792-451a-b905-011946edc191"]}}}}},"400":{"description":"Missing or invalid organization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"404":{"description":"Requested appointment record was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundErrorResponse"},"example":{"error":"Customer not found"}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["read:appointments"]},"patch":{"operationId":"appointments-update","tags":["Appointments"],"summary":"Update appointment timing, assignment, or lifecycle state.","description":"Update appointment timing, assignment, or lifecycle state. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentUpsertRequest"},"example":{"customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","scheduled_start":"2026-03-24T13:00:00.000Z","scheduled_end":"2026-03-24T15:00:00.000Z","assigned_team_member_ids":["95cb6a1e-3792-451a-b905-011946edc191"]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAppointmentResponse"},"example":{"data":{"id":"10bdff89-2f4f-4f06-8595-5f971ca0119a","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"confirmed","scheduled_start":"2026-03-24T13:00:00.000Z","scheduled_end":"2026-03-24T15:00:00.000Z","assigned_team_member_ids":["95cb6a1e-3792-451a-b905-011946edc191"]}}}}},"400":{"description":"Missing organization context or invalid request payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"404":{"description":"Requested appointment record was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundErrorResponse"},"example":{"error":"Customer not found"}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["write:appointments"]}},"/api/public/v1/estimates":{"get":{"operationId":"estimates-list","tags":["Estimates"],"summary":"List estimates with status, customer, and date-based filtering.","description":"List estimates with status, customer, and date-based filtering. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateListResponse"},"example":{"data":[{"id":"97e08590-a443-4725-aa47-7e3cc767a28d","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","currency":"USD","subtotal_amount":1825,"total_amount":1950}],"pagination":{"count":2,"limit":25,"next_cursor":null}}}}},"400":{"description":"Missing or invalid organization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["read:estimates"]},"post":{"operationId":"estimates-create","tags":["Estimates"],"summary":"Create a new estimate with service lines and pricing metadata.","description":"Create a new estimate with service lines and pricing metadata. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEstimateRequest"},"example":{"customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","currency":"USD","line_items":[{"name":"Quarterly hood cleaning","quantity":1,"unit_price":1825}]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateResponse"},"example":{"data":{"id":"97e08590-a443-4725-aa47-7e3cc767a28d","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","currency":"USD","subtotal_amount":1825,"total_amount":1950}}}}},"201":{"description":"Created response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateResponse"},"example":{"data":{"id":"97e08590-a443-4725-aa47-7e3cc767a28d","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","currency":"USD","subtotal_amount":1825,"total_amount":1950}}}}},"400":{"description":"Missing organization context or invalid request payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"404":{"description":"Referenced customer record was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundErrorResponse"},"example":{"error":"Customer not found"}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["write:estimates"]}},"/api/public/v1/estimates/{estimateId}":{"get":{"operationId":"estimates-get","tags":["Estimates"],"summary":"Retrieve one estimate and current pricing status.","description":"Retrieve one estimate and current pricing status. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateResponse"},"example":{"data":{"id":"97e08590-a443-4725-aa47-7e3cc767a28d","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","currency":"USD","subtotal_amount":1825,"total_amount":1950}}}}},"400":{"description":"Missing or invalid organization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"404":{"description":"Requested estimate record was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundErrorResponse"},"example":{"error":"Customer not found"}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["read:estimates"]}},"/api/public/v1/estimates/{estimateId}/send":{"post":{"operationId":"estimates-send","tags":["Estimates"],"summary":"Trigger delivery of an estimate to the customer.","description":"Trigger delivery of an estimate to the customer. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateSendResponse"},"example":{"data":{"estimate_id":"97e08590-a443-4725-aa47-7e3cc767a28d","status":"queued"}}}}},"201":{"description":"Created response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateSendResponse"},"example":{"data":{"estimate_id":"97e08590-a443-4725-aa47-7e3cc767a28d","status":"queued"}}}}},"400":{"description":"Missing organization context or invalid request payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"404":{"description":"Requested estimate record was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundErrorResponse"},"example":{"error":"Customer not found"}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["write:estimates"]}},"/api/public/v1/invoices":{"get":{"operationId":"invoices-list","tags":["Invoices"],"summary":"List invoices by customer, status, or date range.","description":"List invoices by customer, status, or date range. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceListResponse"},"example":{"data":[{"id":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","payment_status":"pending","balance_due":1950,"due_date":"2026-04-15"}],"pagination":{"count":2,"limit":25,"next_cursor":null}}}}},"400":{"description":"Missing or invalid organization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["read:invoices"]},"post":{"operationId":"invoices-create","tags":["Invoices"],"summary":"Create an invoice with line items, due dates, and balance state.","description":"Create an invoice with line items, due dates, and balance state. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateInvoiceRequest"},"example":{"customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","due_date":"2026-04-15","line_items":[{"name":"Kitchen exhaust cleaning","quantity":1,"unit_price":1950}]}}}},"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceResponse"},"example":{"data":{"id":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","payment_status":"pending","balance_due":1950,"due_date":"2026-04-15"}}}}},"201":{"description":"Created response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceResponse"},"example":{"data":{"id":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","payment_status":"pending","balance_due":1950,"due_date":"2026-04-15"}}}}},"400":{"description":"Missing organization context or invalid request payload.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["write:invoices"]}},"/api/public/v1/invoices/{invoiceId}":{"get":{"operationId":"invoices-get","tags":["Invoices"],"summary":"Retrieve one invoice and current balance/payment metadata.","description":"Retrieve one invoice and current balance/payment metadata. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvoiceResponse"},"example":{"data":{"id":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","payment_status":"pending","balance_due":1950,"due_date":"2026-04-15"}}}}},"400":{"description":"Missing or invalid organization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"404":{"description":"Requested invoice record was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundErrorResponse"},"example":{"error":"Customer not found"}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["read:invoices"]}},"/api/public/v1/payments":{"get":{"operationId":"payments-list","tags":["Payments"],"summary":"List payments by customer, invoice, status, or date range.","description":"List payments by customer, invoice, status, or date range. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentListResponse"},"example":{"data":[{"id":"1fc10a48-2c62-4d17-a7f1-4b1f42cb6c84","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","invoice_id":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e","amount":1950,"status":"completed","payment_method":"card","payment_date":"2026-03-22","created_at":"2026-03-22T15:40:12.000Z"}],"pagination":{"count":2,"limit":25,"next_cursor":null}}}}},"400":{"description":"Missing or invalid organization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["read:payments"]}},"/api/public/v1/payments/{paymentId}":{"get":{"operationId":"payments-get","tags":["Payments"],"summary":"Retrieve one payment and its invoice/customer linkage.","description":"Retrieve one payment and its invoice/customer linkage. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaymentResponse"},"example":{"data":{"id":"1fc10a48-2c62-4d17-a7f1-4b1f42cb6c84","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","invoice_id":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e","amount":1950,"status":"completed","payment_method":"card","payment_date":"2026-03-22","created_at":"2026-03-22T15:40:12.000Z"}}}}},"400":{"description":"Missing or invalid organization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"404":{"description":"Requested payment record was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundErrorResponse"},"example":{"error":"Customer not found"}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["read:payments"]}},"/api/public/v1/services":{"get":{"operationId":"services-list","tags":["Services"],"summary":"List services by active state, catalog visibility, or search query.","description":"List services by active state, catalog visibility, or search query. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceListResponse"},"example":{"data":[{"id":"10fbd700-2b14-44c8-8b7b-f7786b3d9f74","name":"Kitchen exhaust cleaning","description":"Full hood, duct, and fan cleaning service.","price":1950,"duration_minutes":180,"is_active":true,"service_type":"commercial_kitchen","created_at":"2026-03-18T15:40:12.000Z"}],"pagination":{"count":2,"limit":25,"next_cursor":null}}}}},"400":{"description":"Missing or invalid organization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["read:services"]}},"/api/public/v1/services/{serviceId}":{"get":{"operationId":"services-get","tags":["Services"],"summary":"Retrieve one service and its public catalog metadata.","description":"Retrieve one service and its public catalog metadata. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceResponse"},"example":{"data":{"id":"10fbd700-2b14-44c8-8b7b-f7786b3d9f74","name":"Kitchen exhaust cleaning","description":"Full hood, duct, and fan cleaning service.","price":1950,"duration_minutes":180,"is_active":true,"service_type":"commercial_kitchen","created_at":"2026-03-18T15:40:12.000Z"}}}}},"400":{"description":"Missing or invalid organization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"404":{"description":"Requested service record was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundErrorResponse"},"example":{"error":"Customer not found"}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["read:services"]}},"/api/public/v1/files":{"get":{"operationId":"files-list","tags":["Files"],"summary":"List files by status, content type, or filename search.","description":"List files by status, content type, or filename search. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileListResponse"},"example":{"data":[{"id":"1e8e8395-5581-4ad0-8462-0b4780d2fdd2","original_name":"before-cleaning-photo.jpg","content_type":"image/jpeg","size_bytes":452301,"status":"ready","bucket":"uploads","created_at":"2026-03-18T15:40:12.000Z"}],"pagination":{"count":2,"limit":25,"next_cursor":null}}}}},"400":{"description":"Missing or invalid organization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["read:files"]}},"/api/public/v1/files/{fileId}":{"get":{"operationId":"files-get","tags":["Files"],"summary":"Retrieve one file record and current metadata state.","description":"Retrieve one file record and current metadata state. Status: Private preview.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FileResponse"},"example":{"data":{"id":"1e8e8395-5581-4ad0-8462-0b4780d2fdd2","original_name":"before-cleaning-photo.jpg","content_type":"image/jpeg","size_bytes":452301,"status":"ready","bucket":"uploads","created_at":"2026-03-18T15:40:12.000Z"}}}}},"400":{"description":"Missing or invalid organization context.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BadRequestErrorResponse"},"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}}}},"401":{"description":"Missing, invalid, or expired API credentials.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnauthorizedErrorResponse"},"example":{"error":"Invalid API key"}}}},"403":{"description":"Missing scopes or organization access for this request.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForbiddenErrorResponse"},"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}}}},"404":{"description":"Requested file record was not found.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotFoundErrorResponse"},"example":{"error":"Customer not found"}}}},"429":{"description":"Configured API key rate limit exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RateLimitErrorResponse"},"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}}}},"500":{"description":"Unexpected preview API failure.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InternalServerErrorResponse"},"example":{"error":"Failed to fetch customers"}}}}},"x-asteri-status":"Private preview","x-asteri-scopes":["read:files"]}},"customer.created | customer.updated | customer.deleted":{"post":{"operationId":"webhook-events-customers","tags":["Webhook Events"],"summary":"Customer lifecycle events delivered to subscribed webhook endpoints.","description":"Customer lifecycle events delivered to subscribed webhook endpoints. Status: Available now.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEventPayload"},"example":{"event":"customer.created","timestamp":"2026-03-20T14:30:00.000Z","data":{"id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","organization_id":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d"}}}}},"201":{"description":"Created response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEventPayload"},"example":{"event":"customer.created","timestamp":"2026-03-20T14:30:00.000Z","data":{"id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","organization_id":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d"}}}}}},"x-asteri-status":"Available now","x-asteri-scopes":["manage:webhooks"]}},"appointment.created | appointment.updated | appointment.completed | appointment.cancelled":{"post":{"operationId":"webhook-events-appointments","tags":["Webhook Events"],"summary":"Appointment lifecycle events delivered with signed payloads.","description":"Appointment lifecycle events delivered with signed payloads. Status: Available now.","security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"parameters":[{"name":"x-organization-id","in":"header","required":true,"schema":{"type":"string","format":"uuid"},"description":"Active organization context for the request."}],"responses":{"200":{"description":"Successful response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEventPayload"},"example":{"event":"customer.created","timestamp":"2026-03-20T14:30:00.000Z","data":{"id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","organization_id":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d"}}}}},"201":{"description":"Created response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEventPayload"},"example":{"event":"customer.created","timestamp":"2026-03-20T14:30:00.000Z","data":{"id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","organization_id":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d"}}}}}},"x-asteri-status":"Available now","x-asteri-scopes":["manage:webhooks"]}}},"components":{"securitySchemes":{"apiKeyAuth":{"type":"apiKey","in":"header","name":"x-api-key","description":"Scoped Asteri API key for server-to-server public API access."},"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Authenticated Asteri session token or API key via Authorization: Bearer ast_live_..."}},"schemas":{"Customer":{"type":"object","description":"Canonical public representation of a customer record in Asteri.","properties":{"id":{"type":"string","format":"uuid","description":"Stable customer identifier.","example":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3"},"organization_id":{"type":"string","format":"uuid","description":"Organization that owns the record.","example":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d"},"account_type":{"type":"string","enum":["individual","business"],"description":"High-level account classification.","example":"business"},"display_name":{"type":"string","description":"Primary display name shown across the platform.","example":"North Harbor Facilities"},"email":{"type":"string","nullable":true,"description":"Primary contact email.","example":"ops@northerborfacilities.com"},"phone":{"type":"string","nullable":true,"description":"Primary contact phone number.","example":"+1-404-555-0128"},"created_at":{"type":"string","format":"date-time","description":"ISO-8601 timestamp for record creation.","example":"2026-03-18T15:40:12.000Z"}},"required":["id","organization_id","account_type","display_name","email","phone","created_at"],"additionalProperties":false,"example":{"id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","organization_id":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d","account_type":"business","display_name":"North Harbor Facilities","email":"ops@northerborfacilities.com","phone":"+1-404-555-0128","created_at":"2026-03-18T15:40:12.000Z"}},"CreateCustomerRequest":{"type":"object","description":"Payload for creating a customer in the public API.","properties":{"account_type":{"type":"string","enum":["individual","business"],"description":"Account classification used when creating the customer.","example":"business"},"display_name":{"type":"string","description":"Customer display name or company name. Useful when you do not want to provide explicit name fields.","example":"North Harbor Facilities"},"company_name":{"type":"string","description":"Explicit company name for business accounts.","example":"North Harbor Facilities"},"first_name":{"type":"string","description":"Primary contact first name.","example":"Nora"},"last_name":{"type":"string","description":"Primary contact last name.","example":"Harbor"},"email":{"type":"string","description":"Primary contact email.","example":"ops@northerborfacilities.com"},"phone":{"type":"string","description":"Primary contact phone number.","example":"+1-404-555-0128"}},"required":["account_type","email","phone"],"additionalProperties":false,"example":{"account_type":"business","display_name":"North Harbor Facilities","company_name":"North Harbor Facilities","first_name":"Nora","last_name":"Harbor","email":"ops@northerborfacilities.com","phone":"+1-404-555-0128"}},"CustomerListResponse":{"type":"object","description":"Response body for customer list endpoints.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Customer"},"description":"Collection of customers matching the current filter set.","example":[{"id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","organization_id":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d","account_type":"business","display_name":"North Harbor Facilities","email":"ops@northerborfacilities.com","phone":"+1-404-555-0128","created_at":"2026-03-18T15:40:12.000Z"}]},"pagination":{"type":"object","properties":{"count":{"type":"integer","example":2},"limit":{"type":"integer","example":25},"next_cursor":{"type":"string","nullable":true,"example":null}},"required":["count","limit","next_cursor"],"additionalProperties":false,"example":{"count":2,"limit":25,"next_cursor":null},"description":"List metadata for page traversal."}},"required":["data","pagination"],"additionalProperties":false,"example":{"data":[{"id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","organization_id":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d","account_type":"business","display_name":"North Harbor Facilities","email":"ops@northerborfacilities.com","phone":"+1-404-555-0128","created_at":"2026-03-18T15:40:12.000Z"}],"pagination":{"count":2,"limit":25,"next_cursor":null}}},"BadRequestErrorResponse":{"type":"object","description":"Bad-request response returned when required request context or payload shape is invalid.","properties":{"error":{"type":"string","description":"High-level error message.","example":"Missing organization context. Provide x-organization-id."},"issues":{"type":"array","items":{"type":"object","properties":{"path":{"type":"string","example":"email"},"message":{"type":"string","example":"Invalid email address"}},"required":["path","message"],"additionalProperties":false,"example":{"path":"email","message":"Invalid email address"}},"example":[{"path":"email","message":"Invalid email address"}],"description":"Field-level validation issues when the payload shape is invalid."}},"required":["error"],"additionalProperties":false,"example":{"error":"Missing organization context. Provide x-organization-id.","issues":[{"path":"email","message":"Invalid email address"}]}},"UnauthorizedErrorResponse":{"type":"object","description":"Authentication failure returned when the request has no valid API key or session.","properties":{"error":{"type":"string","description":"High-level authentication error message.","example":"Invalid API key"}},"required":["error"],"additionalProperties":false,"example":{"error":"Invalid API key"}},"ForbiddenErrorResponse":{"type":"object","description":"Authorization failure returned when the caller lacks required scopes or organization access.","properties":{"error":{"type":"string","description":"High-level authorization error message.","example":"API key missing required scopes"},"missingScopes":{"type":"array","items":{"type":"string","example":"write:customers"},"example":["write:customers"],"description":"Scopes required for the request when scope-based authorization fails."}},"required":["error"],"additionalProperties":false,"example":{"error":"API key missing required scopes","missingScopes":["write:customers"]}},"RateLimitErrorResponse":{"type":"object","description":"Response returned when an API key exceeds its configured preview request limits.","properties":{"error":{"type":"string","description":"High-level rate-limit error message.","example":"API key minute rate limit exceeded"},"limit":{"type":"integer","description":"Configured limit for the relevant time window.","example":60},"window":{"type":"string","enum":["minute","day"],"description":"Rate-limit window that was exceeded.","example":"minute"}},"required":["error","limit","window"],"additionalProperties":false,"example":{"error":"API key minute rate limit exceeded","limit":60,"window":"minute"}},"InternalServerErrorResponse":{"type":"object","description":"Response returned when the preview API cannot complete the request because of an internal failure.","properties":{"error":{"type":"string","description":"High-level internal error message.","example":"Failed to fetch customers"}},"required":["error"],"additionalProperties":false,"example":{"error":"Failed to fetch customers"}},"CreateCustomerResponse":{"type":"object","description":"Response returned after customer creation.","properties":{"data":{"$ref":"#/components/schemas/Customer","description":"Created customer object."}},"required":["data"],"additionalProperties":false,"example":{"data":{"id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","organization_id":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d","account_type":"business","display_name":"North Harbor Facilities","email":"ops@northerborfacilities.com","phone":"+1-404-555-0128","created_at":"2026-03-18T15:40:12.000Z"}}},"ConflictErrorResponse":{"type":"object","description":"Conflict response returned when the requested mutation violates a uniqueness or state constraint.","properties":{"error":{"type":"string","description":"High-level conflict error message.","example":"Customer email already exists in this organization"},"field":{"type":"string","description":"Field associated with the conflicting value when available.","example":"email"}},"required":["error"],"additionalProperties":false,"example":{"error":"Customer email already exists in this organization","field":"email"}},"CustomerResponse":{"type":"object","description":"Single-customer response body.","properties":{"data":{"$ref":"#/components/schemas/Customer","description":"Requested customer object."}},"required":["data"],"additionalProperties":false,"example":{"data":{"id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","organization_id":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d","account_type":"business","display_name":"North Harbor Facilities","email":"ops@northerborfacilities.com","phone":"+1-404-555-0128","created_at":"2026-03-18T15:40:12.000Z"}}},"NotFoundErrorResponse":{"type":"object","description":"Response returned when the requested resource does not exist in the active organization.","properties":{"error":{"type":"string","description":"High-level not-found error message.","example":"Customer not found"}},"required":["error"],"additionalProperties":false,"example":{"error":"Customer not found"}},"Appointment":{"type":"object","description":"Public representation of a scheduled service appointment.","properties":{"id":{"type":"string","format":"uuid","description":"Stable appointment identifier.","example":"10bdff89-2f4f-4f06-8595-5f971ca0119a"},"customer_id":{"type":"string","format":"uuid","description":"Customer associated with the appointment.","example":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3"},"status":{"type":"string","example":"confirmed","description":"Current lifecycle status."},"scheduled_start":{"type":"string","format":"date-time","description":"Planned appointment start timestamp.","example":"2026-03-24T13:00:00.000Z"},"scheduled_end":{"type":"string","format":"date-time","description":"Planned appointment end timestamp.","example":"2026-03-24T15:00:00.000Z"},"assigned_team_member_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Technician/team assignments for the appointment.","example":["95cb6a1e-3792-451a-b905-011946edc191"]}},"required":["id","customer_id","status","scheduled_start","scheduled_end","assigned_team_member_ids"],"additionalProperties":false,"example":{"id":"10bdff89-2f4f-4f06-8595-5f971ca0119a","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"confirmed","scheduled_start":"2026-03-24T13:00:00.000Z","scheduled_end":"2026-03-24T15:00:00.000Z","assigned_team_member_ids":["95cb6a1e-3792-451a-b905-011946edc191"]}},"AppointmentUpsertRequest":{"type":"object","description":"Payload for creating or updating appointments.","properties":{"customer_id":{"type":"string","format":"uuid","description":"Customer that owns the scheduled work.","example":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3"},"scheduled_start":{"type":"string","format":"date-time","description":"Appointment start timestamp.","example":"2026-03-24T13:00:00.000Z"},"scheduled_end":{"type":"string","format":"date-time","description":"Appointment end timestamp.","example":"2026-03-24T15:00:00.000Z"},"assigned_team_member_ids":{"type":"array","items":{"type":"string","format":"uuid"},"description":"Assigned technicians or team members.","example":["95cb6a1e-3792-451a-b905-011946edc191"]}},"required":["customer_id","scheduled_start","scheduled_end"],"additionalProperties":false,"example":{"customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","scheduled_start":"2026-03-24T13:00:00.000Z","scheduled_end":"2026-03-24T15:00:00.000Z","assigned_team_member_ids":["95cb6a1e-3792-451a-b905-011946edc191"]}},"AppointmentListResponse":{"type":"object","description":"Response body for appointment collection endpoints.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Appointment"},"description":"Appointments matching filters.","example":[{"id":"10bdff89-2f4f-4f06-8595-5f971ca0119a","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"confirmed","scheduled_start":"2026-03-24T13:00:00.000Z","scheduled_end":"2026-03-24T15:00:00.000Z","assigned_team_member_ids":["95cb6a1e-3792-451a-b905-011946edc191"]}]},"pagination":{"type":"object","properties":{"count":{"type":"integer","example":2},"limit":{"type":"integer","example":25},"next_cursor":{"type":"string","nullable":true,"example":null}},"required":["count","limit","next_cursor"],"additionalProperties":false,"example":{"count":2,"limit":25,"next_cursor":null},"description":"List metadata for page traversal."}},"required":["data","pagination"],"additionalProperties":false,"example":{"data":[{"id":"10bdff89-2f4f-4f06-8595-5f971ca0119a","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"confirmed","scheduled_start":"2026-03-24T13:00:00.000Z","scheduled_end":"2026-03-24T15:00:00.000Z","assigned_team_member_ids":["95cb6a1e-3792-451a-b905-011946edc191"]}],"pagination":{"count":2,"limit":25,"next_cursor":null}}},"CreateAppointmentResponse":{"type":"object","description":"Response returned after appointment creation.","properties":{"data":{"$ref":"#/components/schemas/Appointment","description":"Created appointment."}},"required":["data"],"additionalProperties":false,"example":{"data":{"id":"10bdff89-2f4f-4f06-8595-5f971ca0119a","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"confirmed","scheduled_start":"2026-03-24T13:00:00.000Z","scheduled_end":"2026-03-24T15:00:00.000Z","assigned_team_member_ids":["95cb6a1e-3792-451a-b905-011946edc191"]}}},"AppointmentResponse":{"type":"object","description":"Single-appointment response body.","properties":{"data":{"$ref":"#/components/schemas/Appointment","description":"Requested appointment."}},"required":["data"],"additionalProperties":false,"example":{"data":{"id":"10bdff89-2f4f-4f06-8595-5f971ca0119a","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"confirmed","scheduled_start":"2026-03-24T13:00:00.000Z","scheduled_end":"2026-03-24T15:00:00.000Z","assigned_team_member_ids":["95cb6a1e-3792-451a-b905-011946edc191"]}}},"UpdateAppointmentResponse":{"type":"object","description":"Response returned after appointment update.","properties":{"data":{"$ref":"#/components/schemas/Appointment","description":"Updated appointment."}},"required":["data"],"additionalProperties":false,"example":{"data":{"id":"10bdff89-2f4f-4f06-8595-5f971ca0119a","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"confirmed","scheduled_start":"2026-03-24T13:00:00.000Z","scheduled_end":"2026-03-24T15:00:00.000Z","assigned_team_member_ids":["95cb6a1e-3792-451a-b905-011946edc191"]}}},"Estimate":{"type":"object","description":"Public representation of an estimate or quote.","properties":{"id":{"type":"string","format":"uuid","description":"Stable estimate identifier.","example":"97e08590-a443-4725-aa47-7e3cc767a28d"},"customer_id":{"type":"string","format":"uuid","description":"Customer associated with the estimate.","example":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3"},"status":{"type":"string","example":"sent","description":"Estimate lifecycle state."},"currency":{"type":"string","description":"ISO currency code.","example":"USD"},"subtotal_amount":{"type":"number","description":"Subtotal before taxes/fees.","example":1825},"total_amount":{"type":"number","description":"Final estimate amount.","example":1950}},"required":["id","customer_id","status","currency","subtotal_amount","total_amount"],"additionalProperties":false,"example":{"id":"97e08590-a443-4725-aa47-7e3cc767a28d","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","currency":"USD","subtotal_amount":1825,"total_amount":1950}},"CreateEstimateRequest":{"type":"object","description":"Payload for creating an estimate.","properties":{"customer_id":{"type":"string","format":"uuid","description":"Customer receiving the estimate.","example":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3"},"currency":{"type":"string","description":"ISO currency code.","example":"USD"},"line_items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"Quarterly hood cleaning"},"quantity":{"type":"integer","example":1},"unit_price":{"type":"integer","example":1825}},"required":["name","quantity","unit_price"],"additionalProperties":false,"example":{"name":"Quarterly hood cleaning","quantity":1,"unit_price":1825}},"example":[{"name":"Quarterly hood cleaning","quantity":1,"unit_price":1825}],"description":"Estimate line items."}},"required":["customer_id","currency","line_items"],"additionalProperties":false,"example":{"customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","currency":"USD","line_items":[{"name":"Quarterly hood cleaning","quantity":1,"unit_price":1825}]}},"EstimateResponse":{"type":"object","description":"Single-estimate response body.","properties":{"data":{"$ref":"#/components/schemas/Estimate","description":"Requested estimate object."}},"required":["data"],"additionalProperties":false,"example":{"data":{"id":"97e08590-a443-4725-aa47-7e3cc767a28d","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","currency":"USD","subtotal_amount":1825,"total_amount":1950}}},"EstimateListResponse":{"type":"object","description":"Collection response for estimates.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Estimate"},"description":"Estimates matching the current filters.","example":[{"id":"97e08590-a443-4725-aa47-7e3cc767a28d","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","currency":"USD","subtotal_amount":1825,"total_amount":1950}]},"pagination":{"type":"object","properties":{"count":{"type":"integer","example":2},"limit":{"type":"integer","example":25},"next_cursor":{"type":"string","nullable":true,"example":null}},"required":["count","limit","next_cursor"],"additionalProperties":false,"example":{"count":2,"limit":25,"next_cursor":null},"description":"List metadata for page traversal."}},"required":["data","pagination"],"additionalProperties":false,"example":{"data":[{"id":"97e08590-a443-4725-aa47-7e3cc767a28d","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","currency":"USD","subtotal_amount":1825,"total_amount":1950}],"pagination":{"count":2,"limit":25,"next_cursor":null}}},"EstimateSendResponse":{"type":"object","description":"Response returned when estimate delivery is triggered.","properties":{"data":{"type":"object","properties":{"estimate_id":{"type":"string","example":"97e08590-a443-4725-aa47-7e3cc767a28d"},"status":{"type":"string","example":"queued"}},"required":["estimate_id","status"],"additionalProperties":false,"example":{"estimate_id":"97e08590-a443-4725-aa47-7e3cc767a28d","status":"queued"},"description":"Delivery operation result."}},"required":["data"],"additionalProperties":false,"example":{"data":{"estimate_id":"97e08590-a443-4725-aa47-7e3cc767a28d","status":"queued"}}},"Invoice":{"type":"object","description":"Public representation of an invoice record.","properties":{"id":{"type":"string","format":"uuid","description":"Stable invoice identifier.","example":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e"},"customer_id":{"type":"string","format":"uuid","description":"Customer billed by this invoice.","example":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3"},"status":{"type":"string","example":"sent","description":"Invoice lifecycle state."},"payment_status":{"type":"string","example":"pending","description":"Payment collection state for the invoice."},"balance_due":{"type":"number","description":"Current open balance.","example":1950},"due_date":{"type":"string","format":"date","description":"Invoice due date.","example":"2026-04-15"}},"required":["id","customer_id","status","payment_status","balance_due","due_date"],"additionalProperties":false,"example":{"id":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","payment_status":"pending","balance_due":1950,"due_date":"2026-04-15"}},"CreateInvoiceRequest":{"type":"object","description":"Payload for creating an invoice.","properties":{"customer_id":{"type":"string","format":"uuid","description":"Customer billed by the invoice.","example":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3"},"due_date":{"type":"string","format":"date","description":"Invoice due date.","example":"2026-04-15"},"line_items":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","example":"Kitchen exhaust cleaning"},"quantity":{"type":"integer","example":1},"unit_price":{"type":"integer","example":1950}},"required":["name","quantity","unit_price"],"additionalProperties":false,"example":{"name":"Kitchen exhaust cleaning","quantity":1,"unit_price":1950}},"example":[{"name":"Kitchen exhaust cleaning","quantity":1,"unit_price":1950}],"description":"Invoice line items."}},"required":["customer_id","due_date","line_items"],"additionalProperties":false,"example":{"customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","due_date":"2026-04-15","line_items":[{"name":"Kitchen exhaust cleaning","quantity":1,"unit_price":1950}]}},"InvoiceResponse":{"type":"object","description":"Single-invoice response body.","properties":{"data":{"$ref":"#/components/schemas/Invoice","description":"Requested invoice object."}},"required":["data"],"additionalProperties":false,"example":{"data":{"id":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","payment_status":"pending","balance_due":1950,"due_date":"2026-04-15"}}},"InvoiceListResponse":{"type":"object","description":"Collection response for invoices.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Invoice"},"description":"Invoices matching the current filters.","example":[{"id":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","payment_status":"pending","balance_due":1950,"due_date":"2026-04-15"}]},"pagination":{"type":"object","properties":{"count":{"type":"integer","example":2},"limit":{"type":"integer","example":25},"next_cursor":{"type":"string","nullable":true,"example":null}},"required":["count","limit","next_cursor"],"additionalProperties":false,"example":{"count":2,"limit":25,"next_cursor":null},"description":"List metadata for page traversal."}},"required":["data","pagination"],"additionalProperties":false,"example":{"data":[{"id":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","status":"sent","payment_status":"pending","balance_due":1950,"due_date":"2026-04-15"}],"pagination":{"count":2,"limit":25,"next_cursor":null}}},"Payment":{"type":"object","description":"Public representation of a collected or recorded payment.","properties":{"id":{"type":"string","format":"uuid","description":"Stable payment identifier.","example":"1fc10a48-2c62-4d17-a7f1-4b1f42cb6c84"},"customer_id":{"type":"string","format":"uuid","description":"Customer associated with the payment.","example":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3"},"invoice_id":{"type":"string","format":"uuid","description":"Invoice associated with the payment when one exists.","example":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e"},"amount":{"type":"number","description":"Payment amount in the organization currency.","example":1950},"status":{"type":"string","example":"completed","description":"Current lifecycle state for the payment."},"payment_method":{"type":"string","description":"Payment method type recorded on the payment.","example":"card"},"payment_date":{"type":"string","format":"date","description":"Date the payment was collected or recorded.","example":"2026-03-22"},"created_at":{"type":"string","format":"date-time","description":"ISO-8601 timestamp for record creation.","example":"2026-03-22T15:40:12.000Z"}},"required":["id","customer_id","amount","status","payment_method","payment_date","created_at"],"additionalProperties":false,"example":{"id":"1fc10a48-2c62-4d17-a7f1-4b1f42cb6c84","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","invoice_id":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e","amount":1950,"status":"completed","payment_method":"card","payment_date":"2026-03-22","created_at":"2026-03-22T15:40:12.000Z"}},"PaymentListResponse":{"type":"object","description":"Collection response for payments.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Payment"},"description":"Payments matching the current filters.","example":[{"id":"1fc10a48-2c62-4d17-a7f1-4b1f42cb6c84","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","invoice_id":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e","amount":1950,"status":"completed","payment_method":"card","payment_date":"2026-03-22","created_at":"2026-03-22T15:40:12.000Z"}]},"pagination":{"type":"object","properties":{"count":{"type":"integer","example":2},"limit":{"type":"integer","example":25},"next_cursor":{"type":"string","nullable":true,"example":null}},"required":["count","limit","next_cursor"],"additionalProperties":false,"example":{"count":2,"limit":25,"next_cursor":null},"description":"List metadata for page traversal."}},"required":["data","pagination"],"additionalProperties":false,"example":{"data":[{"id":"1fc10a48-2c62-4d17-a7f1-4b1f42cb6c84","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","invoice_id":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e","amount":1950,"status":"completed","payment_method":"card","payment_date":"2026-03-22","created_at":"2026-03-22T15:40:12.000Z"}],"pagination":{"count":2,"limit":25,"next_cursor":null}}},"PaymentResponse":{"type":"object","description":"Single-payment response body.","properties":{"data":{"$ref":"#/components/schemas/Payment","description":"Requested payment object."}},"required":["data"],"additionalProperties":false,"example":{"data":{"id":"1fc10a48-2c62-4d17-a7f1-4b1f42cb6c84","customer_id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","invoice_id":"4dd2dc3d-51a9-4e91-a225-67d1d69cf42e","amount":1950,"status":"completed","payment_method":"card","payment_date":"2026-03-22","created_at":"2026-03-22T15:40:12.000Z"}}},"Service":{"type":"object","description":"Public representation of a service catalog item.","properties":{"id":{"type":"string","format":"uuid","description":"Stable service identifier.","example":"10fbd700-2b14-44c8-8b7b-f7786b3d9f74"},"name":{"type":"string","description":"Display name for the service.","example":"Kitchen exhaust cleaning"},"description":{"type":"string","nullable":true,"description":"Customer-facing service description.","example":"Full hood, duct, and fan cleaning service."},"price":{"type":"number","description":"Base service price.","example":1950},"duration_minutes":{"type":"integer","description":"Default service duration in minutes.","example":180},"is_active":{"type":"boolean","example":true,"description":"Whether the service is currently active and bookable."},"service_type":{"type":"string","nullable":true,"description":"Internal service type classification when present.","example":"commercial_kitchen"},"created_at":{"type":"string","format":"date-time","description":"ISO-8601 timestamp for record creation.","example":"2026-03-18T15:40:12.000Z"}},"required":["id","name","description","price","duration_minutes","is_active","service_type","created_at"],"additionalProperties":false,"example":{"id":"10fbd700-2b14-44c8-8b7b-f7786b3d9f74","name":"Kitchen exhaust cleaning","description":"Full hood, duct, and fan cleaning service.","price":1950,"duration_minutes":180,"is_active":true,"service_type":"commercial_kitchen","created_at":"2026-03-18T15:40:12.000Z"}},"ServiceListResponse":{"type":"object","description":"Collection response for services.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Service"},"description":"Services matching the current filters.","example":[{"id":"10fbd700-2b14-44c8-8b7b-f7786b3d9f74","name":"Kitchen exhaust cleaning","description":"Full hood, duct, and fan cleaning service.","price":1950,"duration_minutes":180,"is_active":true,"service_type":"commercial_kitchen","created_at":"2026-03-18T15:40:12.000Z"}]},"pagination":{"type":"object","properties":{"count":{"type":"integer","example":2},"limit":{"type":"integer","example":25},"next_cursor":{"type":"string","nullable":true,"example":null}},"required":["count","limit","next_cursor"],"additionalProperties":false,"example":{"count":2,"limit":25,"next_cursor":null},"description":"List metadata for page traversal."}},"required":["data","pagination"],"additionalProperties":false,"example":{"data":[{"id":"10fbd700-2b14-44c8-8b7b-f7786b3d9f74","name":"Kitchen exhaust cleaning","description":"Full hood, duct, and fan cleaning service.","price":1950,"duration_minutes":180,"is_active":true,"service_type":"commercial_kitchen","created_at":"2026-03-18T15:40:12.000Z"}],"pagination":{"count":2,"limit":25,"next_cursor":null}}},"ServiceResponse":{"type":"object","description":"Single-service response body.","properties":{"data":{"$ref":"#/components/schemas/Service","description":"Requested service object."}},"required":["data"],"additionalProperties":false,"example":{"data":{"id":"10fbd700-2b14-44c8-8b7b-f7786b3d9f74","name":"Kitchen exhaust cleaning","description":"Full hood, duct, and fan cleaning service.","price":1950,"duration_minutes":180,"is_active":true,"service_type":"commercial_kitchen","created_at":"2026-03-18T15:40:12.000Z"}}},"File":{"type":"object","description":"Public representation of a file record managed by Asteri.","properties":{"id":{"type":"string","format":"uuid","description":"Stable file identifier.","example":"1e8e8395-5581-4ad0-8462-0b4780d2fdd2"},"original_name":{"type":"string","description":"Original uploaded file name.","example":"before-cleaning-photo.jpg"},"content_type":{"type":"string","description":"MIME type recorded for the file.","example":"image/jpeg"},"size_bytes":{"type":"integer","description":"File size in bytes.","example":452301},"status":{"type":"string","description":"Current file processing or availability status.","example":"ready"},"bucket":{"type":"string","description":"Storage bucket used for the file.","example":"uploads"},"created_at":{"type":"string","format":"date-time","description":"ISO-8601 timestamp for record creation.","example":"2026-03-18T15:40:12.000Z"}},"required":["id","original_name","content_type","size_bytes","status","bucket","created_at"],"additionalProperties":false,"example":{"id":"1e8e8395-5581-4ad0-8462-0b4780d2fdd2","original_name":"before-cleaning-photo.jpg","content_type":"image/jpeg","size_bytes":452301,"status":"ready","bucket":"uploads","created_at":"2026-03-18T15:40:12.000Z"}},"FileListResponse":{"type":"object","description":"Collection response for files.","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/File"},"description":"Files matching the current filters.","example":[{"id":"1e8e8395-5581-4ad0-8462-0b4780d2fdd2","original_name":"before-cleaning-photo.jpg","content_type":"image/jpeg","size_bytes":452301,"status":"ready","bucket":"uploads","created_at":"2026-03-18T15:40:12.000Z"}]},"pagination":{"type":"object","properties":{"count":{"type":"integer","example":2},"limit":{"type":"integer","example":25},"next_cursor":{"type":"string","nullable":true,"example":null}},"required":["count","limit","next_cursor"],"additionalProperties":false,"example":{"count":2,"limit":25,"next_cursor":null},"description":"List metadata for page traversal."}},"required":["data","pagination"],"additionalProperties":false,"example":{"data":[{"id":"1e8e8395-5581-4ad0-8462-0b4780d2fdd2","original_name":"before-cleaning-photo.jpg","content_type":"image/jpeg","size_bytes":452301,"status":"ready","bucket":"uploads","created_at":"2026-03-18T15:40:12.000Z"}],"pagination":{"count":2,"limit":25,"next_cursor":null}}},"FileResponse":{"type":"object","description":"Single-file response body.","properties":{"data":{"$ref":"#/components/schemas/File","description":"Requested file object."}},"required":["data"],"additionalProperties":false,"example":{"data":{"id":"1e8e8395-5581-4ad0-8462-0b4780d2fdd2","original_name":"before-cleaning-photo.jpg","content_type":"image/jpeg","size_bytes":452301,"status":"ready","bucket":"uploads","created_at":"2026-03-18T15:40:12.000Z"}}},"WebhookEventPayload":{"type":"object","description":"Signed webhook payload delivered to subscribers.","properties":{"event":{"type":"string","description":"Event name for the lifecycle change that occurred.","example":"customer.created"},"timestamp":{"type":"string","format":"date-time","description":"ISO-8601 event timestamp.","example":"2026-03-20T14:30:00.000Z"},"data":{"type":"object","properties":{"id":{"type":"string","example":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3"},"organization_id":{"type":"string","example":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d"}},"required":["id","organization_id"],"additionalProperties":false,"example":{"id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","organization_id":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d"},"description":"Entity payload associated with the event."}},"required":["event","timestamp","data"],"additionalProperties":false,"example":{"event":"customer.created","timestamp":"2026-03-20T14:30:00.000Z","data":{"id":"8af2ca8e-8f31-4e6e-a46c-0703b61f7ca3","organization_id":"dce3853d-4f94-4bc8-a816-4d0d74c11a9d"}}}}}}