{"openapi":"3.1.0","info":{"title":"LocalService Connector API","version":"2.0.0","description":"Provider-confirmed local service requests. Prices are USD cents. TEST payments only. Create -> awaiting_provider -> awaiting_customer_confirmation or provider_countered -> explicit customer approval -> payment_pending -> verified Stripe webhook -> confirmed -> completed. Decline -> provider_declined. Unpaid cancellation -> cancelled. Paid cancellation at least 24 hours before start -> refund_pending -> refunded. No endpoint silently approves a counteroffer. Provider/admin credentials are separate and must never be exposed to Muse agents.","contact":{"name":"LocalService Support","email":"team@trinityriverai.com","url":"https://localservice.trinityriverai.com/support"}},"servers":[{"url":"https://localservice.trinityriverai.com"}],"security":[{"apiKey":[]},{"bearerAuth":[]}],"paths":{"/api/health":{"get":{"operationId":"health","summary":"Read deployment health","description":"503 if persistence or authentication is unavailable.","responses":{"200":{"description":"Database reachable and safe configuration","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","const":"ok"},"connector":{"type":"string"},"version":{"type":"string"},"storage":{"type":"string","const":"supabase"},"payments":{"type":"object","properties":{"mode":{"type":"string","const":"test_only"},"checkout_configured":{"type":"boolean"},"spt_enabled":{"type":"boolean","const":false},"connect":{"type":"string","const":"deferred"}},"required":["mode","checkout_configured","spt_enabled","connect"],"additionalProperties":false}},"required":["status","connector","version","storage","payments"],"additionalProperties":false}}}},"400":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[]}},"/api/providers":{"get":{"operationId":"listProviders","summary":"List real active providers","description":"Review fixtures are excluded.","responses":{"200":{"description":"Public provider metadata without private contact details","content":{"application/json":{"schema":{"type":"object","properties":{"providers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"postal_codes":{"type":"array","items":{"type":"string"}},"mobile":{"type":"boolean"},"provides_water":{"type":"boolean"},"provides_electricity":{"type":"boolean"},"manual_confirmation":{"type":"boolean","const":true}},"required":["id","name","postal_codes","mobile","provides_water","provides_electricity","manual_confirmation"],"additionalProperties":false}}},"required":["providers"],"additionalProperties":false}}}},"400":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/services":{"get":{"operationId":"listServices","summary":"List real active services","description":"Includes generic variants and add-on prices in cents.","responses":{"200":{"description":"Service catalog","content":{"application/json":{"schema":{"type":"object","properties":{"services":{"type":"array","items":{"$ref":"#/components/schemas/Service"}}},"required":["services"],"additionalProperties":false}}}},"400":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/availability":{"get":{"operationId":"searchAvailability","summary":"Search available services","description":"Times use provider-local schedules with DST. Slots are signed and revalidated at booking. Review fixtures require review=true. No match returns an empty array.","responses":{"200":{"description":"Matches","content":{"application/json":{"schema":{"type":"object","properties":{"slots":{"type":"array","items":{"$ref":"#/components/schemas/Slot"}}},"required":["slots"],"additionalProperties":false}}}},"400":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"date","in":"query","required":true,"schema":{"type":"string","format":"date"}},{"name":"postal_code","in":"query","required":true,"schema":{"type":"string","pattern":"^\\d{5}$"}},{"name":"category","in":"query","required":false,"schema":{"type":"string"}},{"name":"service_id","in":"query","required":false,"schema":{"type":"string"}},{"name":"vehicle_type","in":"query","required":false,"description":"Generic service variant, initially sedan, suv, truck, large_suv.","schema":{"type":"string"}},{"name":"pet_hair","in":"query","required":false,"schema":{"type":"string","enum":["none","moderate","heavy"]}},{"name":"add_ons","in":"query","required":false,"description":"Comma-separated service add-on identifiers.","schema":{"type":"string"}},{"name":"budget_max_cents","in":"query","required":false,"schema":{"type":"integer","minimum":50,"maximum":1000000}},{"name":"time_window","in":"query","required":false,"schema":{"type":"string","enum":["any","morning","afternoon","evening"]}},{"name":"mobile","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]}},{"name":"provides_water","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]}},{"name":"provides_electricity","in":"query","required":false,"schema":{"type":"string","enum":["true","false"]}},{"name":"review","in":"query","required":false,"description":"Set true only for clearly labeled synthetic review inventory.","schema":{"type":"string","enum":["true","false"]}}]}},"/api/bookings":{"post":{"operationId":"createBooking","summary":"Request a service appointment","description":"Creates awaiting_provider, reserves time, returns a stable booking ID and secret booking token. Provider inbox receives the request. Store the token securely. No payment is created.","responses":{"201":{"description":"Booking requested","content":{"application/json":{"schema":{"type":"object","properties":{"booking":{"$ref":"#/components/schemas/Booking"},"booking_token":{"type":"string"},"provider_confirmation_required":{"type":"boolean","const":true}},"required":["booking","booking_token","provider_confirmation_required"],"additionalProperties":false}}}},"400":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"A unique key per logical write. Repeat the identical request with the same key on timeouts; changed input requires a new key.","schema":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[A-Za-z0-9._:-]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateBookingRequest"}}}}}},"/api/bookings/{id}":{"get":{"operationId":"getBooking","summary":"Retrieve current booking","description":"Authoritative persisted status; requires booking capability.","responses":{"200":{"description":"BookingResponse","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingResponse"}}}},"400":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Booking-Token","in":"header","required":true,"description":"Secret capability returned at creation. Keep it private for this booking; never put it in a URL.","schema":{"type":"string"}}]},"patch":{"operationId":"modifyBooking","summary":"Modify an unpaid request","description":"Only draft, awaiting_provider, provider_countered or awaiting_customer_confirmation. Resets provider approval. Cannot change price, provider or service.","responses":{"200":{"description":"BookingResponse","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingResponse"}}}},"400":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Booking-Token","in":"header","required":true,"description":"Secret capability returned at creation. Keep it private for this booking; never put it in a URL.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"A unique key per logical write. Repeat the identical request with the same key on timeouts; changed input requires a new key.","schema":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[A-Za-z0-9._:-]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModifyBookingRequest"}}}}},"delete":{"operationId":"cancelBooking","summary":"Cancel and refund when allowed","description":"Unpaid requests cancel after Checkout expires safely. Paid cancellation needs 24 hours notice and initiates full refund. Retry same key to recover interrupted refund. Completed bookings cannot self-cancel.","responses":{"200":{"description":"BookingResponse","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingResponse"}}}},"400":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Booking-Token","in":"header","required":true,"description":"Secret capability returned at creation. Keep it private for this booking; never put it in a URL.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"A unique key per logical write. Repeat the identical request with the same key on timeouts; changed input requires a new key.","schema":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[A-Za-z0-9._:-]+$"}}]}},"/api/bookings/{id}/confirm":{"post":{"operationId":"confirmBooking","summary":"Approve final terms and open TEST Checkout","description":"Call only after the customer explicitly approved provider, exact time and price. Pass current version and exact terms. Returns payment_pending and booking.checkout_url. Only a verified webhook confirms payment. shared_payment_token always returns payment_not_enabled; do not send raw tokens.","responses":{"200":{"description":"BookingResponse","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingResponse"}}}},"400":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"X-Booking-Token","in":"header","required":true,"description":"Secret capability returned at creation. Keep it private for this booking; never put it in a URL.","schema":{"type":"string"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"A unique key per logical write. Repeat the identical request with the same key on timeouts; changed input requires a new key.","schema":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[A-Za-z0-9._:-]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConfirmRequest"}}}}}},"/api/provider/bookings":{"get":{"operationId":"providerInbox","summary":"Operator/provider review inbox","description":"Protected operator console API. This global admin credential is not a per-business credential and must not be distributed to independent providers.","responses":{"200":{"description":"Up to 100 pending/confirmed bookings","content":{"application/json":{"schema":{"type":"object","properties":{"bookings":{"type":"array","items":{"$ref":"#/components/schemas/Booking"}}},"required":["bookings"],"additionalProperties":false}}}},"400":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"providerKey":[]}],"parameters":[{"name":"provider_id","in":"query","required":true,"schema":{"type":"string","format":"uuid"}}]}},"/api/provider/bookings/{id}/decision":{"post":{"operationId":"providerDecision","summary":"Accept, decline or counter a request","description":"Operator acts with provider authorization. accept preserves time/price. counter needs final_price_cents; suggest_time needs start_time. Customer approval is always required after acceptance or counter.","responses":{"200":{"description":"BookingResponse","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingResponse"}}}},"400":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"providerKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"A unique key per logical write. Repeat the identical request with the same key on timeouts; changed input requires a new key.","schema":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[A-Za-z0-9._:-]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DecisionRequest"}}}}}},"/api/provider/bookings/{id}/complete":{"post":{"operationId":"completeBooking","summary":"Record service completion","description":"Only confirmed and past end time. Idempotent.","responses":{"200":{"description":"BookingResponse","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingResponse"}}}},"400":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"providerKey":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"description":"A unique key per logical write. Repeat the identical request with the same key on timeouts; changed input requires a new key.","schema":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[A-Za-z0-9._:-]+$"}}]}},"/api/provider/onboarding":{"put":{"operationId":"onboardProvider","summary":"Save provider and services","description":"Operator-only protected administration. UUID-based upserts are naturally idempotent. Service IDs cannot move between providers. Postal-code allowlist determines eligibility; radius is informational. Include hours, blackouts, exceptions, variants, add-ons, travel rules and utility availability.","responses":{"200":{"description":"Saved","content":{"application/json":{"schema":{"type":"object","properties":{"provider_id":{"type":"string"},"saved":{"type":"boolean"}},"required":["provider_id","saved"],"additionalProperties":false}}}},"400":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"providerKey":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":true,"description":"A unique key per logical write. Repeat the identical request with the same key on timeouts; changed input requires a new key.","schema":{"type":"string","minLength":8,"maxLength":128,"pattern":"^[A-Za-z0-9._:-]+$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingRequest"}}}}}},"/api/webhooks/stripe":{"post":{"operationId":"stripeWebhook","summary":"Receive signed Stripe events","description":"Stripe-only: raw request signature is verified. TEST events only. Event IDs are persisted atomically with booking/payment updates. Not an agent action.","responses":{"200":{"description":"Event accepted or already processed","content":{"application/json":{"schema":{"type":"object","properties":{"received":{"type":"boolean"},"duplicate":{"type":"boolean"},"ignored":{"type":"boolean"}},"required":["received"],"additionalProperties":false}}}},"400":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"415":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Structured error; inspect code and recovery flags.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[],"parameters":[{"name":"Stripe-Signature","in":"header","required":true,"schema":{"type":"string"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","description":"Stripe Event envelope; raw bytes must match the signature."}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"X-API-Key"},"bearerAuth":{"type":"http","scheme":"bearer"},"providerKey":{"type":"apiKey","in":"header","name":"X-Provider-API-Key"}},"schemas":{"Booking":{"type":"object","properties":{"booking_id":{"type":"string","format":"uuid"},"provider_id":{"type":"string","format":"uuid"},"service_id":{"type":"string","format":"uuid"},"provider_name":{"type":"string"},"service_name":{"type":"string"},"status":{"type":"string","enum":["draft","awaiting_provider","provider_accepted","provider_countered","provider_declined","awaiting_customer_confirmation","payment_pending","confirmed","completed","cancelled","refund_pending","refunded"]},"version":{"type":"integer","minimum":1},"start_time":{"type":"string","format":"date-time"},"end_time":{"type":"string","format":"date-time"},"price":{"type":"object","properties":{"amount":{"type":"integer","minimum":50},"currency":{"type":"string","const":"usd"}},"required":["amount","currency"],"additionalProperties":false},"customer":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"email":{"type":"string","maxLength":200,"format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"service_address":{"type":"string","minLength":5,"maxLength":300}},"required":["name","email","service_address"],"additionalProperties":false},"vehicle":{"type":"object","properties":{"year":{"type":"string","maxLength":4},"make":{"type":"string","maxLength":40},"model":{"type":"string","maxLength":60},"color":{"type":"string","maxLength":40}},"additionalProperties":false},"notes":{"type":"string"},"selection":{"type":"object"},"is_test":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"payment_status":{"type":"string","enum":["not_requested","pending","paid","failed","refund_pending","refunded"]},"approved_version":{"type":"integer"},"checkout_started_at":{"type":"string","format":"date-time"},"checkout_expires_at":{"type":"integer"},"checkout_session_id":{"type":"string"},"checkout_url":{"type":"string","format":"uri"},"payment_intent_id":{"type":"string"},"refund_id":{"type":"string"},"decision_reason":{"type":"string"}},"required":["booking_id","provider_id","service_id","provider_name","service_name","status","version","start_time","end_time","price","customer","notes","selection","is_test","created_at","updated_at","payment_status"],"additionalProperties":false},"Slot":{"type":"object","properties":{"slot_id":{"type":"string"},"provider_id":{"type":"string"},"provider_name":{"type":"string"},"service_id":{"type":"string"},"service_name":{"type":"string"},"start_time":{"type":"string","format":"date-time"},"end_time":{"type":"string","format":"date-time"},"price":{"type":"object","properties":{"amount":{"type":"integer","minimum":50},"currency":{"type":"string","const":"usd"}},"required":["amount","currency"],"additionalProperties":false},"add_ons":{"type":"array","items":{"type":"string"}},"service_area_eligible":{"type":"boolean","const":true},"provider_confirmation_required":{"type":"boolean","const":true},"is_test":{"type":"boolean"},"provides_water":{"type":"boolean"},"provides_electricity":{"type":"boolean"},"restrictions":{"type":"array","items":{"type":"string"}},"estimated":{"type":"boolean","const":true}},"required":["slot_id","provider_id","provider_name","service_id","service_name","start_time","end_time","price","add_ons","service_area_eligible","provider_confirmation_required","is_test","provides_water","provides_electricity","restrictions","estimated"],"additionalProperties":false},"BookingResponse":{"type":"object","properties":{"booking":{"$ref":"#/components/schemas/Booking"}},"required":["booking"],"additionalProperties":false},"CreateBookingRequest":{"type":"object","properties":{"slot_id":{"type":"string","maxLength":2000},"customer":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":120},"email":{"type":"string","maxLength":200,"format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"service_address":{"type":"string","minLength":5,"maxLength":300}},"required":["name","email","service_address"],"additionalProperties":false},"vehicle":{"type":"object","properties":{"year":{"type":"string","maxLength":4},"make":{"type":"string","maxLength":40},"model":{"type":"string","maxLength":60},"color":{"type":"string","maxLength":40}},"additionalProperties":false},"notes":{"default":"","type":"string","maxLength":1000}},"required":["slot_id","customer"],"additionalProperties":false,"examples":[{"slot_id":"COPY_FROM_SEARCH","customer":{"name":"Review Customer","email":"review@example.com","service_address":"Synthetic review address, 75067"},"vehicle":{"year":"2022","make":"Ford","model":"Explorer","color":"black"},"notes":"Review only"}]},"ModifyBookingRequest":{"type":"object","properties":{"slot_id":{"type":"string","maxLength":2000},"notes":{"type":"string","maxLength":1000}},"additionalProperties":false},"ConfirmRequest":{"type":"object","properties":{"provider_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"start_time":{"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|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"amount_cents":{"type":"integer","minimum":50,"maximum":1000000},"currency":{"type":"string","const":"usd"},"version":{"type":"integer","exclusiveMinimum":0,"maximum":9007199254740991},"approved":{"type":"boolean","const":true},"payment_method":{"default":"checkout","type":"string","enum":["checkout","shared_payment_token"]}},"required":["provider_id","start_time","amount_cents","currency","version","approved"],"additionalProperties":false,"examples":[{"provider_id":"11111111-1111-4111-8111-111111111111","start_time":"2030-01-10T20:00:00.000Z","amount_cents":23900,"currency":"usd","version":2,"approved":true,"payment_method":"checkout"}]},"DecisionRequest":{"type":"object","properties":{"decision":{"type":"string","enum":["accept","decline","counter","suggest_time"]},"final_price_cents":{"type":"integer","minimum":50,"maximum":1000000},"start_time":{"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|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$"},"reason":{"type":"string","maxLength":500}},"required":["decision"],"additionalProperties":false},"OnboardingRequest":{"type":"object","properties":{"provider":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string","minLength":2,"maxLength":120},"active":{"type":"boolean"},"is_test":{"type":"boolean"},"email":{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"phone":{"type":"string","maxLength":30},"postal_codes":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{5}$"}},"home_postal_code":{"type":"string","pattern":"^\\d{5}$"},"radius_miles":{"type":"number","minimum":0,"maximum":200},"timezone":{"type":"string","maxLength":80},"mobile":{"type":"boolean"},"provides_water":{"type":"boolean"},"provides_electricity":{"type":"boolean"},"minimum_notice_hours":{"type":"number","minimum":1,"maximum":168},"manual_confirmation":{"type":"boolean","const":true},"travel_surcharge_cents":{"type":"integer","minimum":0,"maximum":50000},"hours":{"maxItems":21,"type":"array","items":{"type":"object","properties":{"day":{"type":"integer","minimum":1,"maximum":7},"start":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},"end":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"}},"required":["day","start","end"],"additionalProperties":false}},"blackout_dates":{"maxItems":366,"type":"array","items":{"type":"string","format":"date","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])))$"}},"exceptions":{"maxItems":100,"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date","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])))$"},"start":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},"end":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"}},"required":["date","start","end"],"additionalProperties":false}},"stripe_account_id":{"type":"string","pattern":"^acct_"}},"required":["id","name","active","is_test","email","postal_codes","home_postal_code","radius_miles","timezone","mobile","provides_water","provides_electricity","minimum_notice_hours","manual_confirmation","travel_surcharge_cents","hours","blackout_dates","exceptions"],"additionalProperties":false},"services":{"minItems":1,"maxItems":30,"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"provider_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"category":{"type":"string","minLength":1,"maxLength":80},"name":{"type":"string","minLength":2,"maxLength":120},"description":{"type":"string","maxLength":1000},"duration_minutes":{"type":"integer","minimum":15,"maximum":720},"active":{"type":"boolean"},"currency":{"type":"string","const":"usd"},"variants":{"type":"object","propertyNames":{"type":"string","maxLength":40},"additionalProperties":{"type":"integer","minimum":50,"maximum":1000000}},"add_ons":{"type":"object","propertyNames":{"type":"string","maxLength":60},"additionalProperties":{"type":"integer","minimum":0,"maximum":100000}},"pet_hair_rules":{"type":"object","properties":{"moderate":{"type":"string","maxLength":60},"heavy":{"type":"string","maxLength":60}},"required":["moderate","heavy"],"additionalProperties":false}},"required":["id","provider_id","category","name","description","duration_minutes","active","currency","variants","add_ons"],"additionalProperties":false}}},"required":["provider","services"],"additionalProperties":false},"Provider":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"name":{"type":"string","minLength":2,"maxLength":120},"active":{"type":"boolean"},"is_test":{"type":"boolean"},"email":{"type":"string","format":"email","pattern":"^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$"},"phone":{"type":"string","maxLength":30},"postal_codes":{"minItems":1,"maxItems":100,"type":"array","items":{"type":"string","pattern":"^\\d{5}$"}},"home_postal_code":{"type":"string","pattern":"^\\d{5}$"},"radius_miles":{"type":"number","minimum":0,"maximum":200},"timezone":{"type":"string","maxLength":80},"mobile":{"type":"boolean"},"provides_water":{"type":"boolean"},"provides_electricity":{"type":"boolean"},"minimum_notice_hours":{"type":"number","minimum":1,"maximum":168},"manual_confirmation":{"type":"boolean","const":true},"travel_surcharge_cents":{"type":"integer","minimum":0,"maximum":50000},"hours":{"maxItems":21,"type":"array","items":{"type":"object","properties":{"day":{"type":"integer","minimum":1,"maximum":7},"start":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},"end":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"}},"required":["day","start","end"],"additionalProperties":false}},"blackout_dates":{"maxItems":366,"type":"array","items":{"type":"string","format":"date","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])))$"}},"exceptions":{"maxItems":100,"type":"array","items":{"type":"object","properties":{"date":{"type":"string","format":"date","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])))$"},"start":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"},"end":{"type":"string","pattern":"^([01]\\d|2[0-3]):[0-5]\\d$"}},"required":["date","start","end"],"additionalProperties":false}},"stripe_account_id":{"type":"string","pattern":"^acct_"}},"required":["id","name","active","is_test","email","postal_codes","home_postal_code","radius_miles","timezone","mobile","provides_water","provides_electricity","minimum_notice_hours","manual_confirmation","travel_surcharge_cents","hours","blackout_dates","exceptions"],"additionalProperties":false},"Service":{"type":"object","properties":{"id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"provider_id":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$"},"category":{"type":"string","minLength":1,"maxLength":80},"name":{"type":"string","minLength":2,"maxLength":120},"description":{"type":"string","maxLength":1000},"duration_minutes":{"type":"integer","minimum":15,"maximum":720},"active":{"type":"boolean"},"currency":{"type":"string","const":"usd"},"variants":{"type":"object","propertyNames":{"type":"string","maxLength":40},"additionalProperties":{"type":"integer","minimum":50,"maximum":1000000}},"add_ons":{"type":"object","propertyNames":{"type":"string","maxLength":60},"additionalProperties":{"type":"integer","minimum":0,"maximum":100000}},"pet_hair_rules":{"type":"object","properties":{"moderate":{"type":"string","maxLength":60},"heavy":{"type":"string","maxLength":60}},"required":["moderate","heavy"],"additionalProperties":false}},"required":["id","provider_id","category","name","description","duration_minutes","active","currency","variants","add_ons"],"additionalProperties":false},"Error":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"retryable":{"type":"boolean"},"request_id":{"type":"string"},"search_again":{"type":"boolean"},"customer_confirmation_required":{"type":"boolean"},"provider_action_required":{"type":"boolean"}},"required":["code","message","retryable","request_id","search_again","customer_confirmation_required","provider_action_required"],"additionalProperties":false}},"required":["error"],"additionalProperties":false}}}}