{"openapi":"3.1.0","info":{"title":"MyLook — Core Platform API","description":"Foundation / Core Platform v1.0. Contract-first: this specification is the source for the typed client the apps consume.","version":"1.0.0"},"paths":{"/v1/auth/register":{"post":{"tags":["identity"],"summary":"Create an account","operationId":"register_v1_auth_register_post","parameters":[{"name":"user-agent","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User-Agent"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RegisterIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/phone-verification":{"get":{"tags":["identity"],"summary":"Can a code be sent at all? (his §4)","description":"Public, and deliberately blunt. A screen that knows a code cannot arrive can skip the\nstep instead of drawing six empty cells nobody can fill.","operationId":"phone_verification_availability_v1_auth_phone_verification_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Phone Verification Availability V1 Auth Phone Verification Get"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/phone/start":{"post":{"tags":["identity"],"summary":"Send me a code (his §4)","description":"Rate-limited per number AND per machine: one number must not be ground down, and one\nmachine must not walk a list of them.","operationId":"start_phone_verification_v1_auth_phone_start_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhoneStartIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Start Phone Verification V1 Auth Phone Start Post"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/phone/verify":{"post":{"tags":["identity"],"summary":"Here is the code (his §10 — the server decides)","description":"The server checks it. A wrong code, an expired one, one nobody asked for and one already\nused all answer the same way his screen draws: that code did not work.","operationId":"verify_phone_v1_auth_phone_verify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PhoneVerifyIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Verify Phone V1 Auth Phone Verify Post"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/login":{"post":{"tags":["identity"],"summary":"Sign in","operationId":"login_v1_auth_login_post","parameters":[{"name":"user-agent","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"User-Agent"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/refresh":{"post":{"tags":["identity"],"summary":"Exchange a refresh token","operationId":"refresh_v1_auth_refresh_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenPair"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/logout":{"post":{"tags":["identity"],"summary":"Sign out this device","operationId":"logout_v1_auth_logout_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshIn"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/logout-all":{"post":{"tags":["identity"],"summary":"Sign out everywhere","operationId":"logout_all_v1_auth_logout_all_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Logout All V1 Auth Logout All Post"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/auth/forgot-password":{"post":{"tags":["identity"],"summary":"Send a password reset link","description":"Answers the same way whether or not the address is registered.\n\nRate limited on BOTH the address and the caller's IP: the first stops one\ninbox being used as a weapon, the second stops a script walking a list.","operationId":"forgot_password_v1_auth_forgot_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForgotPasswordIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/reset-password":{"post":{"tags":["identity"],"summary":"Choose a new password using the emailed link","operationId":"reset_password_v1_auth_reset_password_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/verify-email":{"post":{"tags":["identity"],"summary":"Confirm an email address","operationId":"verify_email_v1_auth_verify_email_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyEmailIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/auth/verification-code":{"get":{"tags":["identity"],"summary":"His ONB-003 — where the code went, and the countdown","operationId":"verification_status_v1_auth_verification_code_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationStatusOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"post":{"tags":["identity"],"summary":"Send me a six-digit code","description":"HIS DECISION OF 2026-09-05: e-mail until Twilio is wired.\n\nTWO LIMITS, and they are different problems. `one_time_codes` throttles the\nRESEND — sixty seconds between codes, which is the countdown his screen\ndraws. This guard is the hourly ceiling shared with the rest of recovery: a\nperson who waits sixty seconds each time must still not be able to send\nthemselves four hundred e-mails overnight.","operationId":"send_verification_code_v1_auth_verification_code_post","responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationStatusOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/auth/verification-code/confirm":{"post":{"tags":["identity"],"summary":"Confirm the six-digit code","description":"The code is spent whether or not it was right — see `redeem`.\n\nAn IP guard as well as the per-code attempt ceiling: the ceiling protects\nONE code, and somebody willing to request a fresh code every minute would\notherwise get five new guesses each time.","operationId":"confirm_verification_code_v1_auth_verification_code_confirm_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationCodeIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/auth/resend-verification":{"post":{"tags":["identity"],"summary":"Send the confirmation email again","operationId":"resend_verification_v1_auth_resend_verification_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptedOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/admin/staff":{"get":{"tags":["identity","admin"],"summary":"Who holds a platform role — his Roles & Permissions","description":"Newest grant first. Until today a role could only be granted by SQL; the\nfirst administrator of an environment still is (DEPLOY-staging.md), every\ngrant after that comes through here and lands on the audit trail.","operationId":"list_platform_staff_v1_admin_staff_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"include_revoked","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Revoked"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/StaffOut"},"title":"Response List Platform Staff V1 Admin Staff Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["identity","admin"],"summary":"Grant or change a platform role (administrators)","description":"Grant, re-grant a revoked role, or change the role someone holds — with a\nreason. An administrator cannot change their own role (409 cannot_change_self).","operationId":"grant_platform_role_v1_admin_staff_post","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffGrantIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/staff/{user_id}/revoke":{"post":{"tags":["identity","admin"],"summary":"Revoke a platform role (administrators)","description":"The row stays, dated; the person is an ordinary user again from their next\nrequest on. Nobody revokes their own role (409 cannot_revoke_self).","operationId":"revoke_platform_role_v1_admin_staff__user_id__revoke_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffRevokeIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/staff/2fa":{"get":{"tags":["identity","admin"],"summary":"Which staff accounts are protected","description":"The standing answer, not a log: who is enrolled, who is pending, who is\nnot protected at all, and how many recovery codes each has left.","operationId":"staff_two_factor_status_v1_admin_staff_2fa_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/StaffTwoFactorOut"},"type":"array","title":"Response Staff Two Factor Status V1 Admin Staff 2Fa Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/admin/staff/{user_id}/2fa/disable":{"post":{"tags":["identity","admin"],"summary":"Clear another staff member's second factor","description":"A lost phone with the recovery codes in a drawer nobody can reach.\n\nThe reason is mandatory in this contract and mandatory in the database, the\nsubject is emailed, every one of their sessions ends, and the record cannot\nbe edited or deleted afterwards. See twofactor.disable_for_other for why\nthis is not the bypass.","operationId":"disable_staff_two_factor_v1_admin_staff__user_id__2fa_disable_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwoFactorAdminDisableIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwoFactorDisabledOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/staff/{user_id}/2fa/events":{"get":{"tags":["identity","admin"],"summary":"One staff member's two-factor history","description":"Every enrolment, failure, replay, recovery-code use, lockout and\ndisablement, newest first.","operationId":"staff_two_factor_events_v1_admin_staff__user_id__2fa_events_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TwoFactorEventOut"},"title":"Response Staff Two Factor Events V1 Admin Staff  User Id  2Fa Events Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/users/{user_id}/sessions":{"delete":{"tags":["identity","admin"],"summary":"Sign an account out everywhere (staff)","description":"DOC-003 page 7 §9 and §7 (administrative functions): a compromised or\ndeparted account is signed out of every device at once. Recorded twice —\nhere, with the count, and by the request middleware like every /admin call.","operationId":"revoke_user_sessions_v1_admin_users__user_id__sessions_delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Revoke User Sessions V1 Admin Users  User Id  Sessions Delete"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/users/{user_id}/suspend":{"post":{"tags":["identity","admin"],"summary":"Suspend an account (staff)","description":"His decision 17, and the sentence that shapes it: \"for a suspended person\nthe system must PROTECT existing appointments and money: never auto-delete\nor auto-cancel without an explicit rule.\"\n\nSo this changes two things — signing in is refused, and the sessions they\nalready have end. `touches` in the answer names everything it does NOT do,\nbecause a staff member taking this decision is owed the boundary of it.","operationId":"suspend_account_v1_admin_users__user_id__suspend_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuspendIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuspensionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/users/{user_id}/reinstate":{"post":{"tags":["identity","admin"],"summary":"Lift a suspension (staff)","operationId":"reinstate_account_v1_admin_users__user_id__reinstate_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuspendIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuspensionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/users/{user_id}/suspensions":{"get":{"tags":["identity","admin"],"summary":"Every decision ever taken about this account","operationId":"account_history_v1_admin_users__user_id__suspensions_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SuspensionEventOut"},"title":"Response Account History V1 Admin Users  User Id  Suspensions Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/audit":{"get":{"tags":["identity","admin"],"summary":"The audit trail — every administrative request and session anomaly","description":"Newest first. Reading this is an administrative request and is recorded\nlike any other — the trail shows who looked at the trail.","operationId":"read_audit_v1_admin_audit_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"entity_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Type"}},{"name":"entity_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Entity Id"}},{"name":"actor_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Actor Id"}},{"name":"action","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Action"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AuditEntryOut"},"title":"Response Read Audit V1 Admin Audit Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/audit/exports":{"post":{"tags":["identity","admin"],"summary":"Export the trail — CSV or JSON, filtered, and itself on the trail","description":"Administrators only. Answers a SIGNED link good for ten minutes that\ndownloads exactly this export — the signature covers every filter, so the\nlink cannot be widened afterwards — and writes `audit.exported` on the trail\nwith the format, the filters and the row count.","operationId":"export_audit_v1_admin_audit_exports_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditExportIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuditExportOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/admin/audit/export":{"get":{"tags":["identity","admin"],"summary":"Download an export — the signed link POST /admin/audit/exports answered","description":"No session: the signature is the permission, and it expires. This request\nis on the trail too, like every other under /admin.","operationId":"download_audit_export_v1_admin_audit_export_get","parameters":[{"name":"format","in":"query","required":false,"schema":{"enum":["csv","json"],"type":"string","default":"csv","title":"Format"}},{"name":"entity_type","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Type"}},{"name":"entity_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Entity Id"}},{"name":"actor_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Actor Id"}},{"name":"action","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Action"}},{"name":"since","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Since"}},{"name":"until","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Until"}},{"name":"max_id","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Id"}},{"name":"exp","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Exp"}},{"name":"sig","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sig"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/fraud/alerts":{"get":{"tags":["identity","admin"],"summary":"The fraud queue — facts waiting on a human","description":"High first, then oldest. NOT a risk score — nothing on this platform can\ncompute one honestly, and his decision 26 is explicit about inventing\nnumbers.","operationId":"fraud_queue_v1_admin_fraud_alerts_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"alert_status","in":"query","required":false,"schema":{"type":"string","default":"open","title":"Alert Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FraudAlertOut"},"title":"Response Fraud Queue V1 Admin Fraud Alerts Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["identity","admin"],"summary":"Raise one (staff)","description":"A member of staff who saw something. The oldest and most reliable signal\nin any marketplace, and the one nobody builds.","operationId":"raise_fraud_alert_v1_admin_fraud_alerts_post","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FraudAlertIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FraudAlertOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/fraud/alerts/{alert_id}/resolve":{"post":{"tags":["identity","admin"],"summary":"Close one","operationId":"resolve_fraud_alert_v1_admin_fraud_alerts__alert_id__resolve_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"alert_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Alert Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveAlertIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FraudAlertOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me":{"get":{"tags":["identity"],"summary":"The signed-in person","description":"Who this is, including whether they are MyLook staff.\n\nWithout `platform_role` the apps had nothing to route on: an administrator\nsigned in and got the client's Discover screen, because as far as this\ncontract was concerned that is all they were.","operationId":"me_v1_me_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"patch":{"tags":["identity"],"summary":"Edit my own profile","description":"There was a GET here and nothing else, so nobody could set their own name,\nphone or photograph — the Profile screen had a picture it could upload and\nnowhere to put the key.\n\nA duplicate phone number is a 409 rather than a 500: `users.phone` is\nUNIQUE, and two people typing the same number is an ordinary mistake that\ndeserves an ordinary answer.","operationId":"update_me_v1_me_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeUpdateIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/notification-settings":{"get":{"tags":["identity"],"summary":"What I said about being notified (his registration screen 5)","description":"Absent is NOT a no: a person who has never been asked has expressed nothing.","operationId":"read_notification_settings_v1_me_notification_settings_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationSettingsOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"put":{"tags":["identity"],"summary":"Yes, enable notifications - or Not now","description":"HIS §10: this records what the PERSON chose. The operating system's own dialogue comes\nafter the tap and the OS decides - a device that then refuses is the notification\ninfrastructure's business, not this row's.","operationId":"save_notification_settings_v1_me_notification_settings_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationSettingsIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationSettingsOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/social-follows":{"get":{"tags":["identity"],"summary":"The follow links I tapped (his interest signal)","operationId":"read_follow_clicks_v1_me_social_follows_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/FollowClickOut"},"type":"array","title":"Response Read Follow Clicks V1 Me Social Follows Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"post":{"tags":["identity"],"summary":"I tapped Follow on one of MyLook's accounts","description":"A TAP, not a follow. The tap leaves for another app and nothing comes back, so the\nplatform records what it can honestly know - his \"si quieren medir interes\".","operationId":"record_follow_click_v1_me_social_follows_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FollowClickIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FollowClickOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/username-available":{"get":{"tags":["identity"],"summary":"Is this @handle free? — his ONB-007","description":"What his field calls while somebody types, debounced by the app.\n\nCase-insensitive, because @AlexBarber and @alexbarber are one handle to\nevery person who reads them. Suggestions are offered on a taken one — his\nscreen shows up to three chips — and they are checked too, so a suggestion\nis never itself unavailable.","operationId":"username_available_v1_me_username_available_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"handle","in":"query","required":true,"schema":{"type":"string","title":"Handle"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UsernameAvailabilityOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/sessions":{"get":{"tags":["identity"],"summary":"Active devices","operationId":"my_sessions_v1_me_sessions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SessionOut"},"type":"array","title":"Response My Sessions V1 Me Sessions Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/sessions/{session_id}":{"delete":{"tags":["identity"],"summary":"Sign out one device","description":"DOC-003 page 7 §9. `POST /auth/logout` needs the refresh token of the device\nbeing signed out — which is on THAT device. This ends a session by its id\nfrom any other device; the revoked device's access token stops working on\nits next request, not at its expiry.","operationId":"revoke_my_session_v1_me_sessions__session_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"session_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Session Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/2fa":{"get":{"tags":["identity"],"summary":"Whether my account has a second factor","operationId":"my_two_factor_v1_me_2fa_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwoFactorStatusOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/2fa/start":{"post":{"tags":["identity"],"summary":"Begin enrolling an authenticator app","description":"Returns the secret ONCE, and switches nothing on.\n\nEnrolment does not protect the account and does not restrict it either until\na code comes back from the app — see POST /2fa/confirm. Somebody who scans\nthe code and never finishes is exactly where they started.","operationId":"start_two_factor_v1_me_2fa_start_post","responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwoFactorEnrolmentOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/2fa/confirm":{"post":{"tags":["identity"],"summary":"Prove the app works, and switch protection on","description":"The recovery codes are in this response and in no other, ever.","operationId":"confirm_two_factor_v1_me_2fa_confirm_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwoFactorConfirmIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecoveryCodesOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/2fa/verify":{"post":{"tags":["identity"],"summary":"Present the second factor for this session","description":"Signing in is the first factor; this is the second.\n\nThe proof attaches to the SESSION that presented it, not to the person —\notherwise one administrator entering a code would quietly elevate an\nattacker's session on the same account.","operationId":"verify_two_factor_v1_me_2fa_verify_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwoFactorProofIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwoFactorVerifiedOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/2fa/recovery-codes":{"post":{"tags":["identity"],"summary":"Issue a new set of recovery codes","description":"Every previous unused code stops working the moment this returns.","operationId":"new_recovery_codes_v1_me_2fa_recovery_codes_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwoFactorProofIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecoveryCodesOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/2fa/disable":{"post":{"tags":["identity"],"summary":"Turn off my own two-factor authentication","description":"Asks for a current code — the factor being removed proves the removal.\n\nWithout that, a stolen password would be enough to take the second factor\noff and walk in, which would make the whole feature decorative.","operationId":"disable_my_two_factor_v1_me_2fa_disable_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TwoFactorProofIn"}}},"required":true},"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Too many attempts.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}},"headers":{"Retry-After":{"description":"Seconds to wait before trying again.","schema":{"type":"integer"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/context":{"get":{"tags":["identity"],"summary":"Which MyLook context I am in","description":"HIS GATE 2 — \"Active context survives relaunch/login\".\n\nIt survives because the answer is resolved here, from the identity, rather\nthan remembered by one device: a phone that was force-closed, a second phone\nand a fresh sign-in all ask this and all get the same answer.","operationId":"my_context_v1_me_context_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContextOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"put":{"tags":["identity"],"summary":"Switch to Client, or back to Professional","description":"His switch, \"de forma explícita\" — a person asking, never the app deciding.\n\nOnly for the signed-in identity: the context is read from the session, so a\nbody naming somebody else changes nothing about them.","operationId":"switch_context_v1_me_context_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContextIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContextOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/onboarding-checkpoint":{"get":{"tags":["identity"],"summary":"Where I got to in his onboarding (his §63)","operationId":"read_checkpoint_v1_me_onboarding_checkpoint_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckpointOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"put":{"tags":["identity"],"summary":"Remember where I got to, so a relaunch does not start again","description":"A NAME THE APP CHOOSES, and nothing here reads it.\n\nHis §63's example is \"PROFESSION_COMPLETED\". The flow it describes is the app's, so a\ndatabase enum would have to be migrated every time he moves a screen - and this grants\nnothing: no rule, no capability and no route reads this column.","operationId":"save_checkpoint_v1_me_onboarding_checkpoint_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckpointIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckpointOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/context/history":{"get":{"tags":["identity"],"summary":"My own context switches (his §61 — audit, not a screen)","description":"Their own, newest first. Nobody else's: the identity comes from the session.","operationId":"my_context_history_v1_me_context_history_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ContextSwitchOut"},"title":"Response My Context History V1 Me Context History Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/account/deletion":{"post":{"tags":["privacy"],"summary":"Delete my account","description":"His Delete Account flow, step 2 (\"Verify & Delete\"): the person types DELETE.\n\nIdentity is the signed-in session; authority is checked here (an account that\nowns a business, or a staff account, is refused with 409 and the refusal is\nregistered). Future appointments are cancelled as the person's own\ncancellation, reviews, favorites, threads and the person's files are\ndeleted, memberships stop renewing, the professional profile (if any) is\ndeactivated, every session ends, and the identity row is anonymised. What\nSTD-002 page 7 §32 makes the platform keep — appointment, payment and order\nrecords, the audit trail — is listed in `kept`, and no longer names anyone.\n\nThe answer is the last thing this account ever receives: its sessions are\nalready over when it is sent.","operationId":"delete_my_account_v1_me_account_deletion_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountDeletionIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountDeletionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/admin/data-requests":{"get":{"tags":["privacy","admin"],"summary":"The data-request register","description":"DOC-002 page 4 §11.6 — Compliance Management keeps the Data Requests. Every\ndeletion, completed or refused, newest first, with what the platform did.","operationId":"list_data_requests_v1_admin_data_requests_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(deletion|export)$"},{"type":"null"}],"title":"Kind"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(completed|refused)$"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DataRequestOut"},"title":"Response List Data Requests V1 Admin Data Requests Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/support/cases":{"post":{"tags":["support"],"summary":"Open a support case","description":"About one thing — an appointment, an order, a payment, a review, a membership,\na business, or the account itself. The platform reads the parties from it: the\ncustomer of the thing, or an active member of the business, may open the case;\nanybody else is refused (403 not_a_party).","operationId":"open_case_v1_support_cases_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseOpenIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/support/cases/mine":{"get":{"tags":["support"],"summary":"My support cases","description":"As the customer, or through the businesses I belong to. Newest activity first.","operationId":"my_cases_v1_support_cases_mine_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/CaseOut"},"type":"array","title":"Response My Cases V1 Support Cases Mine Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/support/cases/{case_id}":{"get":{"tags":["support"],"summary":"One of my cases","operationId":"my_case_v1_support_cases__case_id__get","security":[{"BearerAuth":[]}],"parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/support/cases/{case_id}/messages":{"post":{"tags":["support"],"summary":"Reply on my case","operationId":"reply_v1_support_cases__case_id__messages_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__support__schemas__MessageIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__support__schemas__MessageOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/support/cases/{case_id}/evidence":{"post":{"tags":["support"],"summary":"Attach evidence to my case","description":"A file already uploaded through POST /media with kind `support_evidence`.","operationId":"attach_evidence_v1_support_cases__case_id__evidence_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__support__schemas__EvidenceIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__support__schemas__EvidenceOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/support/summary":{"get":{"tags":["support","admin"],"summary":"The Command Center counters","operationId":"support_summary_v1_admin_support_summary_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__support__schemas__SummaryOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/admin/support/cases":{"get":{"tags":["support","admin"],"summary":"The Case Queue","description":"SLA-urgent first, then newest. Active cases unless a status or\ninclude_resolved says otherwise; `q` matches the case number, the customer,\nthe business or the subject. `mine_queues` narrows to the categories the\nagent has a skill for — empty when they have none.\n\nPaged by keyset — his approval of Option A, 2026-09-10: pass the previous\npage's `next_cursor` as `cursor`. It is null only on the last page, and a\ncursor issued under different filters is refused rather than obeyed.","operationId":"case_queue_v1_admin_support_cases_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(open|in_review|waiting|escalated|resolved)$"},{"type":"null"}],"title":"Status"}},{"name":"priority","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(critical|urgent|high|medium|low)$"},{"type":"null"}],"title":"Priority"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(booking|payments|orders|accounts|safety_fraud|reviews)$"},{"type":"null"}],"title":"Category"}},{"name":"assignee","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"'me' or a staff user id","title":"Assignee"},"description":"'me' or a staff user id"},{"name":"unassigned","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Unassigned"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Q"}},{"name":"include_resolved","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Resolved"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"mine_queues","in":"query","required":false,"schema":{"type":"boolean","description":"his decision 93: only the queues I work","default":false,"title":"Mine Queues"},"description":"his decision 93: only the queues I work"},{"name":"cursor","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"description":"the previous page's next_cursor; opaque","title":"Cursor"},"description":"the previous page's next_cursor; opaque"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CasePageOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["support","admin"],"summary":"Create Case — on a customer's behalf","description":"His Deep Operations Hub's \"Create Case\". Source staff; the parties are read\nfrom the thing the case is about, or named here.","operationId":"staff_open_case_v1_admin_support_cases_post","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffCaseOpenIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/support/agents":{"get":{"tags":["support","admin"],"summary":"Who works cases, and which queues (his decision 93)","description":"Support Queues + Skills, never tiers: every case-working staff account\nwith the queues it works and the active cases on its desk.","operationId":"support_agents_v1_admin_support_agents_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/AgentOut"},"type":"array","title":"Response Support Agents V1 Admin Support Agents Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/admin/support/agents/{user_id}/skills":{"put":{"tags":["support","admin"],"summary":"Set the queues an agent works (his decision 93)","description":"Replaces the set. An administrator decides; a queue is one of the drawn\ncategories; a person who does not work cases has no queues (404).","operationId":"set_agent_skills_v1_admin_support_agents__user_id__skills_put","security":[{"BearerAuth":[]}],"parameters":[{"name":"user_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"User Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillsIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/support/cases/{case_id}":{"get":{"tags":["support","admin"],"summary":"Case Details","operationId":"case_detail_v1_admin_support_cases__case_id__get","security":[{"BearerAuth":[]}],"parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["support","admin"],"summary":"Triage a case","description":"Priority (the SLA goal follows it, as drawn: 30m · 1h · 2h · 4h · 6h from\ncreation), impact, assignee, tags, or In Review. Assigning an open case puts it\nin review.","operationId":"triage_case_v1_admin_support_cases__case_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TriageIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/support/cases/{case_id}/messages":{"post":{"tags":["support","admin"],"summary":"Reply, or add an internal note","operationId":"staff_message_v1_admin_support_cases__case_id__messages_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__support__schemas__MessageIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__support__schemas__MessageOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/support/cases/{case_id}/evidence":{"post":{"tags":["support","admin"],"summary":"Attach evidence","operationId":"staff_evidence_v1_admin_support_cases__case_id__evidence_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__support__schemas__EvidenceIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__support__schemas__EvidenceOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/support/cases/{case_id}/request-info":{"post":{"tags":["support","admin"],"summary":"Request more information","description":"The case waits on the customer or the professional; the message goes to\nthem; their reply puts it back in review.","operationId":"request_more_info_v1_admin_support_cases__case_id__request_info_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestInfoIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/support/cases/{case_id}/escalate":{"post":{"tags":["support","admin"],"summary":"Escalate a case","description":"Marked escalated, tagged, recorded. Who the specialist team is has no\ndefinition yet (owner question 100); the case stays in the same queue.","operationId":"escalate_case_v1_admin_support_cases__case_id__escalate_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/support/cases/{case_id}/resolve":{"post":{"tags":["support","admin"],"summary":"Resolve a case","description":"Approved, rejected or closed, always with the note the parties receive. A\ncase about a review resolved as rejected may remove the review from the\nbusiness page (his \"Reject Review\"); the rating is recomputed.","operationId":"resolve_case_v1_admin_support_cases__case_id__resolve_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"case_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Case Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResolveIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CaseOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/support/templates":{"get":{"tags":["support","admin"],"summary":"Templates & Macros","operationId":"templates_v1_admin_support_templates_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/TemplateOut"},"type":"array","title":"Response Templates V1 Admin Support Templates Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"post":{"tags":["support","admin"],"summary":"Add a template","operationId":"add_template_v1_admin_support_templates_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TemplateOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/admin/support/templates/{template_id}":{"delete":{"tags":["support","admin"],"summary":"Retire a template","operationId":"retire_template_v1_admin_support_templates__template_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/knowledge/articles":{"get":{"tags":["knowledge"],"summary":"Published knowledge","description":"Customer Help, Professional Help and Policies — published articles only,\nnewest first. No sign-in needed: help is for the person who cannot get in.","operationId":"public_articles_v1_knowledge_articles_get","parameters":[{"name":"domain","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(customer_help|professional_help|policies)$"},{"type":"null"}],"title":"Domain"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Q"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PublicArticleOut"},"title":"Response Public Articles V1 Knowledge Articles Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/knowledge/articles/{article_id}":{"get":{"tags":["knowledge"],"summary":"Read an article","operationId":"public_article_v1_knowledge_articles__article_id__get","parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Article Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicArticleOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/knowledge/summary":{"get":{"tags":["knowledge","admin"],"summary":"KNOWLEDGE HEALTH and DOMAINS","operationId":"knowledge_summary_v1_admin_knowledge_summary_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__knowledge__schemas__SummaryOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/admin/knowledge/attention":{"get":{"tags":["knowledge","admin"],"summary":"KNOWLEDGE REQUIRING ATTENTION","operationId":"knowledge_attention_v1_admin_knowledge_attention_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ArticleOut"},"title":"Response Knowledge Attention V1 Admin Knowledge Attention Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/knowledge/activity":{"get":{"tags":["knowledge","admin"],"summary":"RECENT KNOWLEDGE ACTIVITY","operationId":"knowledge_activity_v1_admin_knowledge_activity_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":30,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/malu__domains__knowledge__schemas__EventOut"},"title":"Response Knowledge Activity V1 Admin Knowledge Activity Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/knowledge/articles":{"get":{"tags":["knowledge","admin"],"summary":"The Knowledge Library","operationId":"knowledge_articles_v1_admin_knowledge_articles_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(draft|pending_review|published|outdated|archived)$"},{"type":"null"}],"title":"Status"}},{"name":"domain","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(customer_help|professional_help|support_procedures|trust_safety|policies)$"},{"type":"null"}],"title":"Domain"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Q"}},{"name":"owner","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Owner"}},{"name":"include_archived","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Archived"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ArticleOut"},"title":"Response Knowledge Articles V1 Admin Knowledge Articles Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["knowledge","admin"],"summary":"Create an article (draft)","operationId":"create_article_v1_admin_knowledge_articles_post","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/knowledge/articles/{article_id}":{"get":{"tags":["knowledge","admin"],"summary":"Knowledge Workspace","operationId":"read_article_v1_admin_knowledge_articles__article_id__get","security":[{"BearerAuth":[]}],"parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Article Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["knowledge","admin"],"summary":"Save (draft or live)","description":"Fields and blocks. Saving never changes the status: a published article\nstays published (his workspace edits one live), a draft stays a draft.","operationId":"update_article_v1_admin_knowledge_articles__article_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Article Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/knowledge/articles/{article_id}/request-review":{"post":{"tags":["knowledge","admin"],"summary":"Request Review","operationId":"request_review_v1_admin_knowledge_articles__article_id__request_review_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Article Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/knowledge/articles/{article_id}/publish":{"post":{"tags":["knowledge","admin"],"summary":"Publish Article — make this article live","operationId":"publish_article_v1_admin_knowledge_articles__article_id__publish_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Article Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublishIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/knowledge/articles/{article_id}/outdate":{"post":{"tags":["knowledge","admin"],"summary":"Mark outdated","operationId":"outdate_article_v1_admin_knowledge_articles__article_id__outdate_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Article Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/knowledge/articles/{article_id}/archive":{"post":{"tags":["knowledge","admin"],"summary":"Archive","operationId":"archive_article_v1_admin_knowledge_articles__article_id__archive_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Article Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/knowledge/articles/{article_id}/restore":{"post":{"tags":["knowledge","admin"],"summary":"Restore as a draft","operationId":"restore_article_v1_admin_knowledge_articles__article_id__restore_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"article_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Article Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ArticleDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/search":{"get":{"tags":["console","admin"],"summary":"Search anything","description":"His MIDDLE VIEW 1: business, professional, client, payment, ticket — each\nsearched where it lives, grouped. Reports and AI flags have no platform yet\n(owner question 102) and are named as not searchable rather than empty.","operationId":"search_anything_v1_admin_search_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"q","in":"query","required":true,"schema":{"type":"string","minLength":2,"maxLength":120,"title":"Q"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":25,"minimum":1,"default":8,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/hub":{"get":{"tags":["console","admin"],"summary":"Deep Operations Hub","description":"His BOTTOM 1. Facts other domains hold, oldest first; a support case keeps\nits own priority, nothing else is ranked (owner question 102).","operationId":"operations_hub_v1_admin_hub_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HubOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/admin/finance/overview":{"get":{"tags":["console","admin"],"summary":"Financial Operations Workspace","description":"His MIDDLE VIEW 4: Financial Health, Failed Payouts, Pending Transfers,\nRefund Requests (disputes awaiting a response, penalty money held with no\nbeneficiary), Billing Exceptions — the money domain's own rows.","operationId":"finance_overview_v1_admin_finance_overview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FinanceOverviewOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/admin/finance/payouts":{"get":{"tags":["console","admin"],"summary":"Payouts — his View all / Review Payouts","description":"Every payout the platform made or tried to make, newest first, by status.","operationId":"finance_payouts_v1_admin_finance_payouts_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"enum":["pending","in_transit","paid","failed"],"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PayoutRowOut"},"title":"Response Finance Payouts V1 Admin Finance Payouts Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/finance/payouts/{payout_id}/send":{"post":{"tags":["console","admin"],"summary":"Process a pending transfer","operationId":"finance_send_payout_v1_admin_finance_payouts__payout_id__send_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"payout_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Payout Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayoutRowOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/finance/payouts/{payout_id}/retry":{"post":{"tags":["console","admin"],"summary":"Resolve a failed payout","description":"Claims what is owed to the beneficiary into a new payout and sends it; the\nfailed row stays as the record of the failure.","operationId":"finance_retry_payout_v1_admin_finance_payouts__payout_id__retry_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"payout_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Payout Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayoutRowOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/platform":{"get":{"tags":["console","admin"],"summary":"Platform Administration Workspace","description":"His Middle View Viewport 5: configuration status (counted), roles, security,\nthe integrations as they really are, his approved money values read-only, the\nlast three audit entries, and what is not built with its owner question.","operationId":"platform_administration_v1_admin_platform_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformAdministrationOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/admin/settings/verification-escalation":{"get":{"tags":["console","admin"],"summary":"Who receives an escalated review — a role, configured","operationId":"read_escalation_role_v1_admin_settings_verification_escalation_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalationRoleOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"put":{"tags":["console","admin"],"summary":"Point escalated reviews at another platform role (admin)","operationId":"set_escalation_role_v1_admin_settings_verification_escalation_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalationRoleIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalationRoleOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/admin/notification-rules":{"get":{"tags":["console","admin"],"summary":"Notification Rules — routing, channels, what nobody may switch off (his decision 106)","operationId":"notification_rules_v1_admin_notification_rules_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationRulesOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/admin/notification-rules/routing/{event}":{"put":{"tags":["console","admin"],"summary":"Route an operational event to a platform role (admin) — never to nobody","operationId":"set_notification_routing_v1_admin_notification_rules_routing__event__put","security":[{"BearerAuth":[]}],"parameters":[{"name":"event","in":"path","required":true,"schema":{"type":"string","title":"Event"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RoutingIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OperationalRouteOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/notification-rules/kinds/{kind}":{"put":{"tags":["console","admin"],"summary":"Switch e-mail on or off for one kind (admin); the record is never touched","operationId":"set_notification_channel_v1_admin_notification_rules_kinds__kind__put","security":[{"BearerAuth":[]}],"parameters":[{"name":"kind","in":"path","required":true,"schema":{"type":"string","title":"Kind"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelRuleIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChannelRuleOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses":{"post":{"tags":["organization"],"summary":"Create a business (with its first location)","operationId":"create_business_v1_businesses_post","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["organization"],"summary":"Find a business to book at — the Search screen","description":"Public: no sign-in needed to look for a salon.\n\nThis is NOT the directory. /directory/search finds unclaimed harvested listings\n— the seeded map. This finds real businesses someone signed up and opened.\n\nHIS DECISION 72's filters ride on the same call; see discovery.search_businesses.\nA date needs a service: availability is of a service, not of a shop.","operationId":"search_businesses_v1_businesses_get","parameters":[{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":90,"minimum":-90},{"type":"null"}],"description":"Where the person is. Omitted = no distance, no distance sort.","title":"Lat"},"description":"Where the person is. Omitted = no distance, no distance sort."},{"name":"lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":180,"minimum":-180},{"type":"null"}],"title":"Lng"}},{"name":"radius_miles","in":"query","required":false,"schema":{"type":"number","maximum":200,"exclusiveMinimum":0,"default":10.0,"title":"Radius Miles"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"description":"Name or tagline","title":"Q"},"description":"Name or tagline"},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"description":"Category slug, e.g. barbershop","title":"Category"},"description":"Category slug, e.g. barbershop"},{"name":"open_now","in":"query","required":false,"schema":{"type":"boolean","description":"Only businesses open right now, measured in the branch's own timezone","default":false,"title":"Open Now"},"description":"Only businesses open right now, measured in the branch's own timezone"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"new_within_days","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","maximum":90,"minimum":1},{"type":"null"}],"description":"Only businesses that FIRST went live within this many days (directive 3 §10: Discover's 'New Near You' asks 7). Unknown publication dates never qualify.","title":"New Within Days"},"description":"Only businesses that FIRST went live within this many days (directive 3 §10: Discover's 'New Near You' asks 7). Unknown publication dates never qualify."},{"name":"service","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"description":"A service the business must offer, by name ('skin fade'); price and availability are measured on it","title":"Service"},"description":"A service the business must offer, by name ('skin fade'); price and availability are measured on it"},{"name":"min_rating","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":5,"minimum":0},{"type":"null"}],"description":"A floor on the business's average; unrated businesses fall below it","title":"Min Rating"},"description":"A floor on the business's average; unrated businesses fall below it"},{"name":"min_price_cents","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"title":"Min Price Cents"}},{"name":"max_price_cents","in":"query","required":false,"schema":{"anyOf":[{"type":"integer","minimum":0},{"type":"null"}],"title":"Max Price Cents"}},{"name":"accepts_memberships","in":"query","required":false,"schema":{"type":"boolean","description":"Only businesses selling a client membership of their own","default":false,"title":"Accepts Memberships"},"description":"Only businesses selling a client membership of their own"},{"name":"available_on","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Only businesses with a free time for `service` on this date, in the branch's own day; the first free time comes back","title":"Available On"},"description":"Only businesses with a free time for `service` on this date, in the branch's own day; the first free time comes back"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BusinessSearchOut"},"title":"Response Search Businesses V1 Businesses Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/mine":{"get":{"tags":["organization"],"summary":"Businesses the signed-in person belongs to","operationId":"my_businesses_v1_businesses_mine_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/BusinessOut"},"type":"array","title":"Response My Businesses V1 Businesses Mine Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/businesses/{business_id}":{"get":{"tags":["organization"],"summary":"One business","operationId":"read_business_v1_businesses__business_id__get","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["organization"],"summary":"Edit the business profile","operationId":"update_business_v1_businesses__business_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/branches/{branch_id}":{"patch":{"tags":["organization"],"summary":"Edit a location","operationId":"update_branch_v1_businesses__business_id__branches__branch_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"branch_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Branch Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/social":{"get":{"tags":["organization"],"summary":"The shop's social presence","description":"Readable by anybody who may edit the business. What a CLIENT sees is the shop's public\nprofile, which renders the same rows - this is the editor's copy.","operationId":"read_business_social_v1_businesses__business_id__social_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BusinessSocialOut"},"title":"Response Read Business Social V1 Businesses  Business Id  Social Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["organization"],"summary":"Connect the shop's presence - his decision 64","description":"exclude_unset, like every other editor here: a request that mentions only TikTok\ndisconnects TikTok and touches nothing else.","operationId":"set_business_social_v1_businesses__business_id__social_put","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessSocialIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BusinessSocialOut"},"title":"Response Set Business Social V1 Businesses  Business Id  Social Put"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/my-access":{"get":{"tags":["organization"],"summary":"What the caller may do here","operationId":"my_access_v1_businesses__business_id__my_access_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyAccessOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/branches":{"get":{"tags":["organization"],"summary":"Locations","operationId":"list_branches_v1_businesses__business_id__branches_get","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BranchOut"},"title":"Response List Branches V1 Businesses  Business Id  Branches Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["organization"],"summary":"Add a location","operationId":"add_branch_v1_businesses__business_id__branches_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/branches/{branch_id}/capacity-history":{"get":{"tags":["organization"],"summary":"Who changed what this location can do, and when","description":"HIS REFINEMENT 08 — the audit trail for operational capacity.\n\nDeciding that a location stops taking work is not a settings tweak: it\ndecides whether a shop earns money tomorrow and whether people already\nbooked are affected. Reading it takes BRANCH_EDIT — the same standing as\nreading the location — while MAKING the change takes BRANCH_MANAGE.","operationId":"capacity_history_v1_businesses__business_id__branches__branch_id__capacity_history_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"branch_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Branch Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LocationCapacityEventOut"},"title":"Response Capacity History V1 Businesses  Business Id  Branches  Branch Id  Capacity History Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/location-actions":{"get":{"tags":["organization"],"summary":"Locations that stopped taking bookings with appointments standing","operationId":"list_location_actions_v1_businesses__business_id__location_actions_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(open|resolved|dismissed)$"},{"type":"null"}],"default":"open","title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/LocationClosureActionOut"},"title":"Response List Location Actions V1 Businesses  Business Id  Location Actions Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/location-actions/{action_id}/resolve":{"post":{"tags":["organization"],"summary":"Record what the owner decided about those appointments","description":"RECORDS the decision; it does not carry it out.\n\nMoving a booking is a reschedule and cancelling one is a cancellation — both\nexist, both ask the client, and neither is fired from here. His sentence is\nthe reason: MyLook may recommend, never change an appointment's address\nwithout consent.","operationId":"resolve_location_action_v1_businesses__business_id__location_actions__action_id__resolve_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"action_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Action Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationClosureResolveIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationClosureActionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/members":{"get":{"tags":["organization"],"summary":"The team","operationId":"list_members_v1_businesses__business_id__members_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"include_revoked","in":"query","required":false,"schema":{"type":"boolean","description":"Include people whose access has ended. Off by default: the team screen wants today's staff.","default":false,"title":"Include Revoked"},"description":"Include people whose access has ended. Off by default: the team screen wants today's staff."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MemberOut"},"title":"Response List Members V1 Businesses  Business Id  Members Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["organization"],"summary":"Invite someone to the team","description":"CR-SEC-2026-09-14-03 — \"NO CONSENT, NO AUTHORITY.\"\n\nThis route used to write an ACTIVE membership for whoever was named. It now writes an\nINVITATION: the person joins when they accept it, and until then they are not on the team.\nThe same call as POST /{business_id}/invitations, kept for the clients that use this path.","operationId":"invite_member_v1_businesses__business_id__members_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvitationIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvitationOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/invitations":{"post":{"tags":["organization"],"summary":"Invite someone to the team","description":"team.invite, within the caller's scope (his decision 6). A professional is invited to a\nlocation; a phone number finds only a verified one (his decision 9).","operationId":"create_invitation_v1_businesses__business_id__invitations_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvitationIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvitationOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["organization"],"summary":"The team's invitations, newest first","description":"What was asked and what came of it. Before an answer, only what the business typed; a\ndecline carries no reason, because none is stored (his decision 10).","operationId":"list_invitations_v1_businesses__business_id__invitations_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TeamInvitationOut"},"title":"Response List Invitations V1 Businesses  Business Id  Invitations Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/invitations/{invitation_id}/resend":{"post":{"tags":["organization"],"summary":"Send an invitation again","description":"The same invitation again, never a second one; at most once every 24 hours (429\n`resend_too_soon` with Retry-After otherwise). The expiry does not move, and the re-send is\naudited (his answer of 2026-09-14).","operationId":"resend_invitation_v1_businesses__business_id__invitations__invitation_id__resend_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"invitation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Invitation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvitationOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/invitations/{invitation_id}/revoke":{"post":{"tags":["organization"],"summary":"Withdraw an invitation","operationId":"revoke_invitation_v1_businesses__business_id__invitations__invitation_id__revoke_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"invitation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Invitation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamInvitationOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/members/{member_id}":{"get":{"tags":["organization"],"summary":"One member","operationId":"read_member_v1_businesses__business_id__members__member_id__get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"member_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Member Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["organization"],"summary":"Change a member's role, location or permissions","description":"Professional → Manager, one branch → another, extra permissions on or off.\n\nOnly the fields sent are touched, and each dimension that actually changes\nwrites its own entry in the member's history against the caller. A change to\nsomebody else's access carries a reason (409 `reason_required`), and a refused\nescalation is written to the audit log as `authorization.denied` — his answer\nof 2026-09-14.","operationId":"update_member_v1_businesses__business_id__members__member_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"member_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Member Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["organization"],"summary":"End the employment relationship (same as /revoke)","description":"The client's audit named DELETE, and a client that reaches for it should\nnot meet a 405. It is the SAME service call as /revoke — the membership is\nnot deleted, it is ended — and it returns the ended membership so the caller\ncan see the record it left behind.\n\nHis answer to question 179 (2026-09-14): removing somebody else says why, so\nDELETE takes the same body as /revoke. The reason travels in the body, never\nin the URL, where every access log along the way would keep it.","operationId":"delete_member_v1_businesses__business_id__members__member_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"member_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Member Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/MemberActionIn"},{"type":"null"}],"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/members/{member_id}/suspend":{"post":{"tags":["organization"],"summary":"Suspend a member temporarily","description":"They keep their place on the team and stop being able to act. Every\nrequest they make is refused with `membership_suspended` — a distinct code\nfrom `not_a_member`, so the app can say which one it is. Suspending somebody\nelse says why (409 `reason_required`) — his answer to question 179.","operationId":"suspend_member_v1_businesses__business_id__members__member_id__suspend_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"member_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Member Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/MemberActionIn"},{"type":"null"}],"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/members/{member_id}/reactivate":{"post":{"tags":["organization"],"summary":"Give a suspended member their access back","operationId":"reactivate_member_v1_businesses__business_id__members__member_id__reactivate_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"member_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Member Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/MemberActionIn"},{"type":"null"}],"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/members/{member_id}/revoke":{"post":{"tags":["organization"],"summary":"End the employment relationship","description":"Nothing is deleted. The membership keeps its id, its role, when it\nstarted, who invited them, and now who ended it and when — and every event\never written about it stays readable.\n\nA POST rather than only a DELETE because a revocation can carry a reason,\nand a reason must not travel in a URL where it would be written into every\naccess log along the way.","operationId":"revoke_member_v1_businesses__business_id__members__member_id__revoke_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"member_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Member Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/MemberActionIn"},{"type":"null"}],"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MemberOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/members/{member_id}/history":{"get":{"tags":["organization"],"summary":"Every change ever made to this member's access","description":"Newest first, and append-only — there is no route that edits or removes\none of these, which is the only reason the history is worth reading.\n\nRequires TEAM_MANAGE, not TEAM_VIEW: every professional can see who their\ncolleagues are, but \"Marco was suspended on the 4th, by Ana\" is between the\nperson and whoever administers them.","operationId":"member_history_v1_businesses__business_id__members__member_id__history_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"member_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Member Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MemberEventOut"},"title":"Response Member History V1 Businesses  Business Id  Members  Member Id  History Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/setup":{"get":{"tags":["organization"],"summary":"His eight stages, and what is left","description":"Anyone who can see the team can see where setting up has got to.\n\nThe same gate as the review inbox and the metrics: this describes the shop\nto the people who run it and discloses nothing a member could not already\nread one screen at a time.","operationId":"business_setup_v1_businesses__business_id__setup_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetupStateOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/publish":{"post":{"tags":["organization"],"summary":"Go live on MyLook","description":"The one stage that acts — and BUSINESS_EDIT, not TEAM_VIEW.\n\nPutting a shop on the map is not reading about it. The same capability that\ngoverns editing the business governs publishing it, because they are the\nsame power over the same thing.","operationId":"publish_business_v1_businesses__business_id__publish_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/clients":{"post":{"tags":["organization"],"summary":"Add a client — his decision 54","description":"TWO DOORS. `user_id`: the shop's record for somebody who BOOKED, created\nthe first time it is needed — the booking is the basis. Name + contact +\n`basis`: a person the shop knows before they have booked, with the shop's\nown reason for holding their details. An e-mail or phone belonging to an\nexisting account attaches the record to it; a phone already on another\nrecord here is refused (`client_exists`) — the duplicate the platform can\nsee is the one it stops. Answers 200 rather than 201 when the record already\nexisted - to a member carrying that client's contact; anybody else is told a\nclient holds those details (409 client_exists) and given no card\n(CR-SEC-2026-09-15-04).","operationId":"add_client_v1_businesses__business_id__clients_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientRecordOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["organization"],"summary":"The people this shop has served","description":"His CRM, and the endpoint `clients_screen.dart` has called since it was\nbuilt — which did not exist until 2026-09-05.\n\nTwo gates, both his decision 40: a professional sees the people THEY served,\nand money and phone numbers travel only to a reader whose role carries them.","operationId":"business_clients_v1_businesses__business_id__clients_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"branch_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":1000,"minimum":1,"default":500,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ClientRowOut"},"title":"Response Business Clients V1 Businesses  Business Id  Clients Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/clients/{record_id}":{"put":{"tags":["organization"],"summary":"Correct what the shop holds about a client","operationId":"edit_client_v1_businesses__business_id__clients__record_id__put","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"record_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Record Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientRecordOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["organization"],"summary":"Archive a client record (manager) — notes are kept","operationId":"archive_client_v1_businesses__business_id__clients__record_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"record_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Record Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/clients/{record_id}/notes":{"get":{"tags":["organization"],"summary":"What the staff wrote","operationId":"client_notes_v1_businesses__business_id__clients__record_id__notes_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"record_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Record Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ClientNoteOut"},"title":"Response Client Notes V1 Businesses  Business Id  Clients  Record Id  Notes Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["organization"],"summary":"Write a note about a client","operationId":"add_client_note_v1_businesses__business_id__clients__record_id__notes_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"record_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Record Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientNoteIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientNoteOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/clients/{record_id}/notes/{note_id}":{"delete":{"tags":["organization"],"summary":"Remove a note — its author, or a manager","operationId":"delete_client_note_v1_businesses__business_id__clients__record_id__notes__note_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"record_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Record Id"}},{"name":"note_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Note Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/verification":{"get":{"tags":["organization"],"summary":"His five checks, as the business sees them — decision 18","description":"Each check, the document behind it, what MyLook asked for and why. Never an escalation —\nthat is MyLook's own routing.\n\nCR-SEC-2026-09-14-07 — business.verification.read, no longer team.view: \"Do not grant access merely\nbecause a user belongs to the business.\" Every link it hands out is audited.","operationId":"business_verification_v1_businesses__business_id__verification_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessVerificationOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/verification/checks/{kind}/document":{"put":{"tags":["organization"],"summary":"Send the document behind one check — decision 18","description":"CR-SEC-2026-09-14-07 — sending a document for a check that has none takes\nbusiness.verification.upload (or .manage); replacing one already sent takes\nbusiness.verification.manage. The file was uploaded first (POST /media, kind\nverification_document, this business); this attaches it to the check and puts\nthe check in front of a reviewer. Both are audited, and the answer carries the\ndocuments only for a caller who may read them.","operationId":"submit_check_document_v1_businesses__business_id__verification_checks__kind__document_put","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"kind","in":"path","required":true,"schema":{"type":"string","title":"Kind"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckDocumentIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessVerificationOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/businesses":{"get":{"tags":["organization","admin"],"summary":"Businesses awaiting a decision — the review queue","description":"Oldest first, with anything explicitly held for review at the top.\n\nEach row carries the last decision taken on that business and why, so a\nreviewer can see that a colleague already unverified it last week rather\nthan quietly deciding it again.","operationId":"review_queue_v1_admin_businesses_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"enum":["draft","pending_review","active","suspended","all"],"type":"string"},{"type":"null"}],"description":"Omit for the queue proper: everything unverified that has not been suspended.","title":"Status"},"description":"Omit for the queue proper: everything unverified that has not been suspended."},{"name":"verified","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Filter on the tick itself.","title":"Verified"},"description":"Filter on the tick itself."},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"description":"Name or slug","title":"Q"},"description":"Name or slug"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BusinessReviewOut"},"title":"Response Review Queue V1 Admin Businesses Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/businesses/{business_id}/history":{"get":{"tags":["organization","admin"],"summary":"Every decision ever taken about this business","description":"Newest first, and append-only — there is no route that edits or removes\none of these, which is the only reason the history is worth reading.","operationId":"history_v1_admin_businesses__business_id__history_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VerificationEventOut"},"title":"Response History V1 Admin Businesses  Business Id  History Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/businesses/{business_id}/verify":{"post":{"tags":["organization","admin"],"summary":"Grant the verified tick","description":"This is what fills the client's Featured and Distinguished rails. Both\nfilter on `is_verified`, so until a business passes through here it cannot\nappear in either, however well the rails themselves are built.","operationId":"verify_v1_admin_businesses__business_id__verify_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffActionIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/businesses/{business_id}/unverify":{"post":{"tags":["organization","admin"],"summary":"Withdraw the verified tick","description":"The business stays open and bookable — it just stops being one MyLook\nvouches for. Taking it off the map is `suspend`, and they are different\ndecisions with different consequences.","operationId":"unverify_v1_admin_businesses__business_id__unverify_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffActionIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/businesses/{business_id}/reject":{"post":{"tags":["organization","admin"],"summary":"Refuse verification, with the reason","description":"His decision 100 of 2026-09-04: verification has four states, and being\nREFUSED is one of them.\n\nUntil 046 a business that had been looked at and turned down was\nindistinguishable from one nobody had opened yet, so it sat in the queue for\never. A refusal takes it out of the queue and says why, on the trail.\n\nA refusal is NOT a suspension: the business stays on the map and keeps\ntrading under policy. Taking it off the map is `suspend`, a different\ndecision with a different consequence.","operationId":"reject_verification_v1_admin_businesses__business_id__reject_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffActionIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/businesses/{business_id}/suspend":{"post":{"tags":["organization","admin"],"summary":"Take a business off the map","description":"Every discovery path in the platform reads `businesses.status = 'active'`\n— search, Featured, Distinguished, popular services, products, promotions —\nso one status change removes it from all of them at once.\n\nThe owner keeps their account and can still edit the profile. What they\ncannot do is undo this: `service.update_business` refuses a status change on\na suspended business, so the only way back is `reinstate`, here.","operationId":"suspend_v1_admin_businesses__business_id__suspend_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffActionIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/businesses/{business_id}/hold":{"post":{"tags":["organization","admin"],"summary":"Hold a business for review ('pending_review')","description":"Also off the map, but because a decision is PENDING rather than made.\n\n'pending_review' has been in the business_status enum since 002 with nothing\nable to apply it — the same hole as 'suspended'. A state the schema declares\nand no code can reach is a promise the database is keeping alone.","operationId":"hold_v1_admin_businesses__business_id__hold_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffActionIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/businesses/{business_id}/reinstate":{"post":{"tags":["organization","admin"],"summary":"Put a suspended or held business back","description":"Back to whatever it was BEFORE — read from the event that took it off,\nnot assumed to be 'active'. A business suspended while it was still a draft\ncomes back a draft, because reinstating must not publish something its owner\nnever published.","operationId":"reinstate_v1_admin_businesses__business_id__reinstate_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffActionIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/businesses/{business_id}/verification":{"get":{"tags":["organization","admin"],"summary":"His Verification Center — five checks and the documents behind them","description":"CR-SEC-2026-09-14-07: MyLook opens a business's documents here — reviewer role, region, second factor — and\nevery short-lived link this read hands out is written to the audit log against the reviewer.","operationId":"business_verification_admin_v1_admin_businesses__business_id__verification_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessVerificationOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/businesses/{business_id}/verification/checks/{kind}":{"post":{"tags":["organization","admin"],"summary":"Decide one check — verified, changes requested or rejected, with the reason","description":"Section by section, as he asked. The tick is a separate decision (verify\nbelow); a reviewer may grant it with checks still open, and the trail says so.","operationId":"decide_check_v1_admin_businesses__business_id__verification_checks__kind__post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"kind","in":"path","required":true,"schema":{"type":"string","title":"Kind"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CheckDecisionIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessVerificationOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/businesses/{business_id}/request-changes":{"post":{"tags":["organization","admin"],"summary":"Request Changes — ask the business for more, on the record","operationId":"request_changes_v1_admin_businesses__business_id__request_changes_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffActionIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerificationEventOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/businesses/{business_id}/escalate":{"post":{"tags":["organization","admin"],"summary":"Escalate Review — to the configured role, never a named person","operationId":"escalate_review_v1_admin_businesses__business_id__escalate_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffActionIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EscalationDoneOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/overview":{"get":{"tags":["organization","admin"],"summary":"Platform Command Center — the whole screen","description":"Everything his three frozen views need, in one request.\n\nONE REQUEST ON PURPOSE. His TOP view exists so an administrator understands\nthe platform \"in less than 5 seconds\"; a screen that assembles itself from\nnine calls cannot honour that, and a card that arrives late reads as a card\nthat is broken.\n\nREAD ONLY, by his rule: \"No editing inside Command Center.\" Every action a\ncard offers is a link into the domain that owns it.","operationId":"overview_v1_admin_overview_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Overview V1 Admin Overview Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/business-contexts":{"get":{"tags":["team"],"summary":"Which My Business contexts I have - his v1.3 §41","description":"THE SHELL ASKS THE PLATFORM, NOT THE SIGN-UP ANSWER.\n\nOne adaptive My Business renders Owner, Independent and Professional-in-Business from this:\nwhat somebody owns, their own operation, and the places they work at - each with its role, its\nownership, its capabilities and its scope. A person who is only a client gets an empty list,\nwhich is not the same as an empty dashboard.\n\nFacts and capabilities only: no compensation, no payout, no billing, no tax document, no\ntransaction, not one amount of money (his §40).","operationId":"my_business_contexts_v1_me_business_contexts_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/BusinessContextOut"},"type":"array","title":"Response My Business Contexts V1 Me Business Contexts Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/invitations":{"get":{"tags":["team"],"summary":"Invitations I have been sent","description":"Newest first: open ones, and what became of the rest.","operationId":"my_invitations_v1_me_invitations_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/MyInvitationOut"},"type":"array","title":"Response My Invitations V1 Me Invitations Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/invitations/{invitation_id}/accept":{"post":{"tags":["team"],"summary":"Accept an invitation to join a team","description":"The relationship begins here and nowhere else: the membership, and for a professional the\nlocation link as ACCEPTED. Bookable is the business's separate step (his decision 2).","operationId":"accept_invitation_v1_me_invitations__invitation_id__accept_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"invitation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Invitation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyInvitationOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/invitations/{invitation_id}/decline":{"post":{"tags":["team"],"summary":"Decline an invitation","description":"No reason is asked for or kept, so none can reach the business (his decision 10).","operationId":"decline_invitation_v1_me_invitations__invitation_id__decline_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"invitation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Invitation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyInvitationOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/invitations/{invitation_id}/request-new":{"post":{"tags":["team"],"summary":"Ask the business for a new invitation","description":"After declining or missing one. It lifts the 14-day wait (his decision 10) and tells the\nbusiness who asked — the person chose to be named.","operationId":"request_new_invitation_v1_me_invitations__invitation_id__request_new_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"invitation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Invitation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyInvitationOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/relationships":{"get":{"tags":["team"],"summary":"The businesses I work with, and have worked with","operationId":"my_relationships_v1_me_relationships_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/MyRelationshipOut"},"type":"array","title":"Response My Relationships V1 Me Relationships Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/relationships/{business_id}/end":{"post":{"tags":["team"],"summary":"End my relationship with a business","description":"His decision 8 — \"either party may end it\". Every location link and every role at that\nbusiness ends today and stays in the history; the business is told. Appointments are counted\nin the answer and never moved or cancelled. The last owner of a business cannot leave it\n(`last_owner`): somebody has to be able to administer it.","operationId":"end_my_relationship_v1_me_relationships__business_id__end_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/RelationshipEndIn"},{"type":"null"}],"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelationshipEndOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/languages/legacy":{"get":{"tags":["organization","admin"],"summary":"What the taxonomy could not resolve","description":"The queue, and the answer to \"may we drop `languages_legacy` yet\".\n\nThat second half is computed from the queue, never asserted: \"no quiero\nmantener dos Sources of Truth\", and the column goes when nothing is left\nthat a person still owes an answer on.","operationId":"legacy_queue_v1_admin_languages_legacy_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string","pattern":"^(unresolved|mapped|needs_taxonomy|ambiguous|rejected)$"},{"type":"null"}],"default":"unresolved","title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Legacy Queue V1 Admin Languages Legacy Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/languages/legacy/scan":{"post":{"tags":["organization","admin"],"summary":"Look for values the taxonomy cannot resolve","description":"Idempotent and additive. A value already reviewed keeps its decision;\nre-running after the taxonomy is extended is how a `needs_taxonomy` row stops\nbeing found as new.","operationId":"legacy_scan_v1_admin_languages_legacy_scan_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Legacy Scan V1 Admin Languages Legacy Scan Post"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/admin/languages/legacy/{value_id}":{"post":{"tags":["organization","admin"],"summary":"A person decides about one value","description":"`mapped` creates the link for that business as well as closing the row —\ndeciding what the value means and finishing the migration for the shop that\nwrote it are the same act.\n\n`rejected` keeps the row. The value stops being USED, not existing.","operationId":"legacy_resolve_v1_admin_languages_legacy__value_id__post","security":[{"BearerAuth":[]}],"parameters":[{"name":"value_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Value Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyResolveIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LegacyValueOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/languages":{"get":{"tags":["organization","admin"],"summary":"The canonical taxonomy, with its aliases","operationId":"list_languages_v1_admin_languages_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/malu__domains__organization__language_admin__LanguageOut"},"type":"array","title":"Response List Languages V1 Admin Languages Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"post":{"tags":["organization","admin"],"summary":"Extend the taxonomy — his decision 152","description":"\"Si aparece un idioma real que todavía no existe en la tabla canónica,\nampliar correctamente la taxonomía.\"\n\nBoth sides of the platform read this table, so adding here adds for\nprofessionals and for businesses at once — which is the whole reason there is\nonly one of it.","operationId":"add_language_v1_admin_languages_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LanguageIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__organization__language_admin__LanguageOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/admin/languages/{language_id}":{"patch":{"tags":["organization","admin"],"summary":"Correct or retire a language","description":"`is_active = false` retires an entry: it stops being offered and stops\nresolving, and every professional and business that had already chosen it\nkeeps the row. Nothing anybody said about themselves is deleted because\nMyLook changed its mind about a list.","operationId":"update_language_v1_admin_languages__language_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"language_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Language Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LanguageUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__organization__language_admin__LanguageOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/catalog/categories":{"get":{"tags":["catalog"],"summary":"Discover's browse row — the curated launch categories","description":"The five circles his Discover pantalla draws, with their services.\n\nNOT the list a business picks from at signup — that is\n`/catalog/business-types`, which is fifteen. Two of his own screens want two\ndifferent lists out of one table; migration 053 is where that is explained.","operationId":"list_categories_v1_catalog_categories_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/CategoryTreeOut"},"type":"array","title":"Response List Categories V1 Catalog Categories Get"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/catalog/business-types":{"get":{"tags":["catalog"],"summary":"What kind of business do you have? — his ONB-006","description":"His fifteen types. Flat, because a business picks what it IS, not what it\nsells — the services under a category are a different question, asked on a\ndifferent screen.","operationId":"list_business_types_v1_catalog_business_types_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/CategoryOut"},"type":"array","title":"Response List Business Types V1 Catalog Business Types Get"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/catalog/discovery/popular-services":{"get":{"tags":["catalog","discovery"],"summary":"Discover's \"Popular services\" — ranked by real bookings","description":"Public: no sign-in needed. People browse before they have an account.\n\nA ranking of SERVICES, not of shops — `GET /businesses` answers that, and a\nservice could previously only be read one business at a time.\n\nTHE RANK IS COUNTED, NEVER ESTIMATED. It is the number of appointments made\nagainst the service, in the window, at branches inside the radius, in a status\nthat means the booking really happened (018_service_stats.sql lists them, and\nsays why an unpaid hold is not one of them). A service that nobody at that\nbranch can perform is not a candidate at all, whatever its history — no skill,\nno slot, no rail entry.\n\nWHEN THERE IS NOTHING TO RANK the response says `ranked_by:\n\"insufficient_data\"` and returns an empty list, with `bookable_nearby` telling\nthe app whether the area is empty or simply too new. It never falls back to an\narbitrary list of services under the word \"Popular\".","operationId":"popular_services_v1_catalog_discovery_popular_services_get","parameters":[{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":90,"minimum":-90},{"type":"null"}],"description":"Where the person is. Omitted = no distance, no distance sort, and the ranking is platform-wide.","title":"Lat"},"description":"Where the person is. Omitted = no distance, no distance sort, and the ranking is platform-wide."},{"name":"lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":180,"minimum":-180},{"type":"null"}],"title":"Lng"}},{"name":"radius_miles","in":"query","required":false,"schema":{"type":"number","maximum":200,"exclusiveMinimum":0,"default":10.0,"title":"Radius Miles"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"description":"Category slug of the shop offering it, e.g. barbershop","title":"Category"},"description":"Category slug of the shop offering it, e.g. barbershop"},{"name":"window_days","in":"query","required":false,"schema":{"type":"integer","maximum":365,"minimum":1,"description":"How far back the bookings are counted","default":90,"title":"Window Days"},"description":"How far back the bookings are counted"},{"name":"min_bookings","in":"query","required":false,"schema":{"type":"integer","minimum":1,"description":"How many bookings a service needs before it may be called popular. Below this it is left out rather than padded in.","default":1,"title":"Min Bookings"},"description":"How many bookings a service needs before it may be called popular. Below this it is left out rather than padded in."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":10,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PopularServicesOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/catalog/discovery/distinguished-businesses":{"get":{"tags":["catalog","discovery"],"summary":"The rail the client's screen titles \"Platinum members\"","description":"Public. THIS IS NOT A PAID TIER, and the response says so on every call.\n\nThe client's screen has a rail titled \"Platinum members\" and nothing anywhere\ndefines what the tier is. There is no business tier in this platform: `plans`\nand `subscriptions` are CLIENT memberships (Premium, Elite — `audience =\n'client'`). Selling a rail to businesses is a commercial programme with a\nprice, a contract, a commission consequence and a refund policy, and none of\nthat has been decided — so none of it is invented here.\n\nWhat is returned instead is the standing the platform genuinely records:\nbusinesses MyLook has VERIFIED, whose rating clears `min_rating` over at least\n`min_reviews` reviews, ranked by rating, then by how many reviews back it, then\nby distance. `basis` names the rule and `is_paid_tier` is false.\n\nNothing falls back. If nobody nearby qualifies the list is empty, because\npadding it with ordinary businesses would make the word meaningless.","operationId":"distinguished_businesses_v1_catalog_discovery_distinguished_businesses_get","parameters":[{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":90,"minimum":-90},{"type":"null"}],"title":"Lat"}},{"name":"lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":180,"minimum":-180},{"type":"null"}],"title":"Lng"}},{"name":"radius_miles","in":"query","required":false,"schema":{"type":"number","maximum":200,"exclusiveMinimum":0,"default":10.0,"title":"Radius Miles"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"title":"Category"}},{"name":"min_rating","in":"query","required":false,"schema":{"type":"number","maximum":5,"minimum":0,"description":"A caller may be STRICTER than the platform default of 4.5, never looser.","default":4.5,"title":"Min Rating"},"description":"A caller may be STRICTER than the platform default of 4.5, never looser."},{"name":"min_reviews","in":"query","required":false,"schema":{"type":"integer","minimum":0,"description":"Likewise: never fewer than 5.","default":5,"title":"Min Reviews"},"description":"Likewise: never fewer than 5."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":10,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DistinguishedBusinessesOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/catalog/discovery/top-rated":{"get":{"tags":["catalog","discovery"],"summary":"Discover's Top Rated / Highly Rated Near You — the ranking the server owns","description":"Public. HIS DIRECTIVE 3 §6 + §20 (2026-09-06): the Top Rated principle the\napp used — a rating weighed by the evidence behind it — is approved, and the\nrule moves HERE. The app receives the result and presents it; it does not\ndecide the official rule. The whole contract (version, formula, inputs,\ntie-breaking, minimum data, fallback, explanation per item) rides in the\nresponse so it can be read from the outside and held to by a test.","operationId":"top_rated_v1_catalog_discovery_top_rated_get","parameters":[{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":90,"minimum":-90},{"type":"null"}],"title":"Lat"}},{"name":"lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":180,"minimum":-180},{"type":"null"}],"title":"Lng"}},{"name":"radius_miles","in":"query","required":false,"schema":{"type":"number","maximum":200,"exclusiveMinimum":0,"default":10.0,"title":"Radius Miles"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"title":"Category"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":10,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopRatedOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/services":{"get":{"tags":["catalog"],"summary":"Services on offer","operationId":"list_services_v1_businesses__business_id__services_get","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ServiceOut"},"title":"Response List Services V1 Businesses  Business Id  Services Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["catalog"],"summary":"Add a service","operationId":"create_service_v1_businesses__business_id__services_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/services/{service_id}":{"patch":{"tags":["catalog"],"summary":"Edit a service","operationId":"update_service_v1_businesses__business_id__services__service_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"service_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Service Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ServiceOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/branches/{branch_id}/services/{service_id}":{"put":{"tags":["catalog"],"summary":"Set a location's price for a service","operationId":"set_branch_service_v1_businesses__business_id__branches__branch_id__services__service_id__put","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"branch_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Branch Id"}},{"name":"service_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Service Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchServiceIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchServiceOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/branches/{branch_id}/services/{service_id}/price":{"get":{"tags":["catalog"],"summary":"The price a client pays at this location","operationId":"branch_price_v1_businesses__business_id__branches__branch_id__services__service_id__price_get","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"branch_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Branch Id"}},{"name":"service_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Service Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Branch Price V1 Businesses  Business Id  Branches  Branch Id  Services  Service Id  Price Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/professionals/{professional_id}/skills":{"post":{"tags":["catalog"],"summary":"Declare a service this professional can perform","operationId":"set_skill_v1_businesses__business_id__professionals__professional_id__skills_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SkillOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true},"get":{"tags":["catalog"],"summary":"What this professional performs","operationId":"list_skills_v1_businesses__business_id__professionals__professional_id__skills_get","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SkillOut"},"title":"Response List Skills V1 Businesses  Business Id  Professionals  Professional Id  Skills Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/products":{"get":{"tags":["catalog"],"summary":"Products for sale","description":"What clients may see: PUBLISHED products only (Shop Manager BR-003).\n\nCarries the variants a client picks between (his decision 80). Without them\nthe app could not buy a product that varies at all — `POST /cart/items`\nrefuses with `variant_required`, correctly, and an app that did not know to\nask would have nothing to send.","operationId":"list_products_v1_businesses__business_id__products_get","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProductOut"},"title":"Response List Products V1 Businesses  Business Id  Products Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["catalog"],"summary":"Add a product (SHOP-05)","operationId":"create_product_v1_businesses__business_id__products_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/products/manage":{"get":{"tags":["catalog"],"summary":"The shop's own catalogue — every status, with stock (SHOP-03)","operationId":"manage_products_v1_businesses__business_id__products_manage_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","minLength":2,"maxLength":100},{"type":"null"}],"description":"Name, SKU or brand — partial, any case","title":"Q"},"description":"Name, SKU or brand — partial, any case"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"array","items":{"enum":["draft","published","archived"],"type":"string"}},{"type":"null"}],"title":"Status"}},{"name":"category_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Category Id"}},{"name":"inventory","in":"query","required":false,"schema":{"anyOf":[{"enum":["in_stock","low_stock","out_of_stock","untracked"],"type":"string"},{"type":"null"}],"title":"Inventory"}},{"name":"sort","in":"query","required":false,"schema":{"enum":["name","price","created","updated"],"type":"string","default":"name","title":"Sort"}},{"name":"order","in":"query","required":false,"schema":{"enum":["asc","desc"],"type":"string","default":"asc","title":"Order"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":100,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProductManageOut"},"title":"Response Manage Products V1 Businesses  Business Id  Products Manage Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/products/{product_id}":{"get":{"tags":["catalog"],"summary":"One product as its shop reads it — record, stock, every decision (SHOP-04)","operationId":"product_detail_v1_businesses__business_id__products__product_id__get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["catalog"],"summary":"Replace a product's record (SHOP-05 — his PUT)","operationId":"update_product_v1_businesses__business_id__products__product_id__put","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductCreateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["catalog"],"summary":"Remove a product (manager or owner) — an archive under BR-004","operationId":"delete_product_v1_businesses__business_id__products__product_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/products/{product_id}/archive":{"patch":{"tags":["catalog"],"summary":"Archive — off sale, history kept (BR-004; manager or owner)","operationId":"archive_product_v1_businesses__business_id__products__product_id__archive_patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/products/{product_id}/restore":{"patch":{"tags":["catalog"],"summary":"Restore an archived product to its permitted state","operationId":"restore_product_v1_businesses__business_id__products__product_id__restore_patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/products/{product_id}/variants":{"get":{"tags":["catalog"],"summary":"What a client picks between","operationId":"list_product_variants_v1_businesses__business_id__products__product_id__variants_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VariantOut"},"title":"Response List Product Variants V1 Businesses  Business Id  Products  Product Id  Variants Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["catalog"],"summary":"Add one, with its own opening count (his decision 80)","operationId":"add_product_variant_v1_businesses__business_id__products__product_id__variants_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VariantIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VariantOut"},"title":"Response Add Product Variant V1 Businesses  Business Id  Products  Product Id  Variants Post"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/products/{product_id}/variants/{variant_id}":{"put":{"tags":["catalog"],"summary":"Edit one — not its stock","operationId":"update_product_variant_v1_businesses__business_id__products__product_id__variants__variant_id__put","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}},{"name":"variant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Variant Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VariantUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VariantOut"},"title":"Response Update Product Variant V1 Businesses  Business Id  Products  Product Id  Variants  Variant Id  Put"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["catalog"],"summary":"Take it off sale — switched off, never deleted (BR-004's rule)","operationId":"remove_product_variant_v1_businesses__business_id__products__product_id__variants__variant_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}},{"name":"variant_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Variant Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VariantOut"},"title":"Response Remove Product Variant V1 Businesses  Business Id  Products  Product Id  Variants  Variant Id  Delete"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/products/{product_id}/images":{"get":{"tags":["catalog"],"summary":"A product's photos, cover first","operationId":"list_product_images_v1_businesses__business_id__products__product_id__images_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProductImageOut"},"title":"Response List Product Images V1 Businesses  Business Id  Products  Product Id  Images Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["catalog"],"summary":"Hang an uploaded photo on a product (his decision 63)","operationId":"add_product_image_v1_businesses__business_id__products__product_id__images_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductImageIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProductImageOut"},"title":"Response Add Product Image V1 Businesses  Business Id  Products  Product Id  Images Post"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["catalog"],"summary":"Reorder the gallery — every photo, in the order you want them","operationId":"reorder_product_images_v1_businesses__business_id__products__product_id__images_put","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductImageOrderIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProductImageOut"},"title":"Response Reorder Product Images V1 Businesses  Business Id  Products  Product Id  Images Put"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/products/{product_id}/images/{image_id}/cover":{"patch":{"tags":["catalog"],"summary":"Make this the one the cards show","operationId":"set_product_cover_v1_businesses__business_id__products__product_id__images__image_id__cover_patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}},{"name":"image_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Image Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProductImageOut"},"title":"Response Set Product Cover V1 Businesses  Business Id  Products  Product Id  Images  Image Id  Cover Patch"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/products/{product_id}/images/{image_id}":{"delete":{"tags":["catalog"],"summary":"Take a photo off — the FILE stays, the media domain owns deletion","operationId":"remove_product_image_v1_businesses__business_id__products__product_id__images__image_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}},{"name":"image_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Image Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProductImageOut"},"title":"Response Remove Product Image V1 Businesses  Business Id  Products  Product Id  Images  Image Id  Delete"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/products/{product_id}/inventory/adjustments":{"post":{"tags":["catalog"],"summary":"Restock or correct stock at a location — audited, never below zero (SHOP-06)","operationId":"adjust_inventory_v1_businesses__business_id__products__product_id__inventory_adjustments_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryAdjustmentIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryAdjustmentOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["catalog"],"summary":"Stock movements for a product, newest first","operationId":"list_adjustments_v1_businesses__business_id__products__product_id__inventory_adjustments_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/InventoryAdjustmentOut"},"title":"Response List Adjustments V1 Businesses  Business Id  Products  Product Id  Inventory Adjustments Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/products/{product_id}/inventory":{"patch":{"tags":["catalog"],"summary":"Set the location's low-stock minimum (BR-008)","operationId":"set_threshold_v1_businesses__business_id__products__product_id__inventory_patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InventoryThresholdIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/InventoryLevelOut"},"title":"Response Set Threshold V1 Businesses  Business Id  Products  Product Id  Inventory Patch"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/membership-plans":{"get":{"tags":["catalog","memberships"],"summary":"The memberships this business sells to its clients","description":"Public: a membership nobody can see is not a product.\n\nTHIS IS NOT A MYLOOK MEMBERSHIP. Joining one of these does not make anybody a\nMyLook member, does not reduce the US$2.99 booking fee, and discounts nothing\nat any other business — the benefit is whatever this shop promised, and this\nshop owes it (§3B; MYLOOK-FIN-RULE-007: \"MyLook proporciona la\ninfraestructura\").\n\nEMPTY IS A REAL ANSWER and has three possible causes, none of which this\nendpoint guesses between for an outsider: the shop sells no memberships, the\nshop is not active on MyLook, or the shop does not hold the Professional Plus\nplan §2 requires to sell them. The owner's own view says which.","operationId":"business_membership_plans_v1_businesses__business_id__membership_plans_get","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BusinessPlanOut"},"title":"Response Business Membership Plans V1 Businesses  Business Id  Membership Plans Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["catalog","memberships"],"summary":"Create a membership this business will sell (owner)","description":"OWNER ONLY, and gated on the US$29.99 Professional Plus plan (§2).\n\nEvery commercial value in the body is the BUSINESS's — name, price, period,\nbenefits. MyLook supplies none of them and defaults none of them. A business\nwithout the Professional Plus subscription is refused with\n`commercial_plan_required`; a business trying to create a professional or\nbusiness plan is refused with `audience_not_yours`, and the database refuses it\nagain (`plans_platform_plans_belong_to_mylook`) if anything gets past that.","operationId":"create_membership_plan_v1_businesses__business_id__membership_plans_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessPlanCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessPlanOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/membership-plans/manage":{"get":{"tags":["catalog","memberships"],"summary":"Every membership, and whether this business may sell them (owner)","description":"The owner's screen. Includes withdrawn plans — without them, withdrawing one\nwould hide it from the only person who might want it back.","operationId":"manage_membership_plans_v1_businesses__business_id__membership_plans_manage_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessMembershipsStateOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/membership-plans/{plan_id}/members":{"get":{"tags":["catalog","memberships"],"summary":"Who holds this membership — the owner's roster","description":"OWNER ONLY, like the console. The names behind the subscriptions, once for\nthe whole list — the Team roster does the same. Another business's plan\nanswers as a missing one (404).","operationId":"membership_plan_members_v1_businesses__business_id__membership_plans__plan_id__members_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"plan_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Plan Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MembershipMemberOut"},"title":"Response Membership Plan Members V1 Businesses  Business Id  Membership Plans  Plan Id  Members Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/membership-plans/{plan_id}":{"patch":{"tags":["catalog","memberships"],"summary":"Edit a membership, or put a withdrawn one back on sale (owner)","description":"Another business's plan answers exactly as a missing one does (404), so this\ncannot be used to discover a competitor's products one id at a time.","operationId":"update_membership_plan_v1_businesses__business_id__membership_plans__plan_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"plan_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Plan Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessPlanUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessPlanOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["catalog","memberships"],"summary":"Withdraw a membership — off sale, not deleted (owner)","description":"Returns the plan rather than a bare 204, because nothing was destroyed.\n\nTHE MEMBERSHIPS ALREADY SOLD ARE UNTOUCHED. They run to the end of the period\neach client paid for. Withdrawing stops NEW clients joining; it does not cancel\nanybody's membership and does not refund anything.\n\nNot gated by §2 — a business whose Professional Plus subscription lapsed must\nstill be able to take its own product off sale.","operationId":"withdraw_membership_plan_v1_businesses__business_id__membership_plans__plan_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"plan_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Plan Id"}},{"name":"reason","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"description":"Why it was withdrawn, in the business's own words. A factual record is written when this is omitted — a withdrawn plan is never left without a reason.","title":"Reason"},"description":"Why it was withdrawn, in the business's own words. A factual record is written when this is omitted — a withdrawn plan is never left without a reason."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessPlanOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/memberships":{"post":{"tags":["catalog","memberships"],"summary":"Join this business's membership","description":"A client joins ONE business's own membership.\n\nOne at a time PER BUSINESS, not per person: a client may hold the barber's and\nthe nail salon's at once, because they are unrelated commercial relationships\nwith unrelated businesses. Refused with `already_a_member_here` for a second at\nthe same shop.\n\nReading and cancelling it afterwards use the subscription endpoints that\nalready exist — `GET /v1/subscriptions/{id}` and\n`POST /v1/subscriptions/{id}/cancel` — because it is the same kind of record\nwith the same at-period-end rule, and a second cancel endpoint is a second\nchance to disagree about what cancelling means.","operationId":"join_business_membership_v1_businesses__business_id__memberships_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BusinessSubscribeIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/plans":{"get":{"tags":["memberships"],"summary":"The CUSTOMER membership plans on offer","description":"Public: the Memberships section exists to be seen by people who have not\njoined. Returned in the order of the client's carousel.\n\nCUSTOMER MEMBERSHIPS ONLY — every plan returned carries `audience: \"client\"`.\nThe plans a professional or a business pays MyLook for are at\n`GET /v1/billing/plans` and can never appear here.\n\nThe two tiers this returns today (Premium US$19.99, Elite US$9.99) have no\napproved source — their only provenance is a screen mock-up, and US$19.99 is\nthe price of the approved PROFESSIONAL subscription. See\ndocs/business-rule-provenance.md §4.3. This audit separated the products; it\ndid not rule on the values.","operationId":"list_plans_v1_plans_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/PlanOut"},"type":"array","title":"Response List Plans V1 Plans Get"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/subscription":{"get":{"tags":["memberships"],"summary":"My customer membership, or null","description":"One that has been cancelled still appears here until its period ends — it is\nstill in force, and `cancelled_at` says it will not renew.\n\nNever returns a platform subscription. If this person's business pays MyLook,\nthat is `GET /v1/businesses/{business_id}/billing/subscription`.","operationId":"my_subscription_v1_me_subscription_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/SubscriptionOut"},{"type":"null"}],"title":"Response My Subscription V1 Me Subscription Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/memberships":{"get":{"tags":["memberships"],"summary":"The BUSINESS memberships I hold","description":"Every membership this person holds that a BUSINESS sells — decision freeze\nv1.0 §3B. A LIST, because any business may sell its own and a client may hold\nseveral at once; each `plan.business_id` says whose it is.\n\nNONE OF THESE MAKES ANYONE A MYLOOK MEMBER. `GET /v1/me/membership` still\nanswers `is_member: false` and `booking_fee_cents: 299` for somebody holding\nten of them: the benefit is the business's to deliver, not MyLook's, and §3C\nforbids v1.0 converting a consumer into a global member by any route.\n\nOne that has been cancelled still appears until its period ends — it is still\nin force, and `cancelled_at` says only that it will not renew.","operationId":"my_business_memberships_v1_me_memberships_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SubscriptionOut"},"type":"array","title":"Response My Business Memberships V1 Me Memberships Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/membership":{"get":{"tags":["memberships"],"summary":"My CUSTOMER membership benefits, resolved on the server","description":"The booking fee here is the fee that will actually be charged — US$2.99, or\nUS$1.99 with a membership in force. The app displays it; it never decides it.\n\nTHIS IS THE CONSUMER PRODUCT. `is_member` is about a customer membership; it\nis not affected by any platform subscription the caller's business may hold,\nand holding one grants no reduction here.\n\nWHEN THE REDUCED FEE APPLIES IS STILL UNDER REVIEW. Today it applies to every\nbooking by anyone holding a membership. DOC-004 authorises it only for a\nservice consumed THROUGH a membership; MYLOOK-FIN-01 §4 lists memberships\namong the things the US$2.99 is independent of. Reported unchanged in\ndocs/business-rule-provenance.md §4.2 — the owner must rule.","operationId":"my_membership_v1_me_membership_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MembershipStateOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/subscriptions":{"post":{"tags":["memberships"],"summary":"Join a customer membership","description":"Refuses a platform plan with `plan_is_not_a_customer_membership`: a\nprofessional or business subscription cannot be sold to a consumer here, and\nthe database refuses the row as well.","operationId":"subscribe_v1_subscriptions_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/subscriptions/{subscription_id}":{"get":{"tags":["memberships"],"summary":"One membership, as its owner","operationId":"get_subscription_v1_subscriptions__subscription_id__get","security":[{"BearerAuth":[]}],"parameters":[{"name":"subscription_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Subscription Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["memberships"],"summary":"Same as /cancel — cancelling is not deleting","description":"DELETE is what an app reaches for, so it is here — but it does exactly what\n/cancel does. It returns the membership, still running, with cancelled_at set,\nrather than a 204 that would suggest the benefits stopped at that moment.","operationId":"delete_subscription_v1_subscriptions__subscription_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"subscription_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Subscription Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/subscriptions/{subscription_id}/cancel":{"post":{"tags":["memberships"],"summary":"Stop it renewing — the benefits run to period end","operationId":"cancel_subscription_v1_subscriptions__subscription_id__cancel_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"subscription_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Subscription Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscriptionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/billing/plans":{"get":{"tags":["billing"],"summary":"The plans a professional or business pays MyLook for","description":"Public, like any pricing page — someone evaluating MyLook has no account yet.\n\nTHIS IS NOT THE MEMBERSHIP CATALOGUE. `GET /v1/plans` returns customer\nmemberships, which are a consumer benefit; this returns what a merchant pays\nto use the platform. Nothing appears in both lists: the audiences are disjoint\nand the database enforces it.\n\nIT IS EMPTY TODAY AND THAT IS DELIBERATE. MYLOOK-PRO-COM-001 approves a\nUS$19.99 professional plan and a US$29.99 professional-business plan, and\nneither is seeded, because their exact codes and names have not been ruled on\n(docs/business-rule-provenance.md §4.4). An empty list is the honest answer;\ninventing a plan to fill it is the failure this platform's audit exists to\nstop.","operationId":"list_platform_plans_v1_billing_plans_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/PlatformPlanOut"},"type":"array","title":"Response List Platform Plans V1 Billing Plans Get"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/billing/subscription":{"get":{"tags":["billing"],"summary":"Does this business pay MyLook for the platform?","description":"Readable by anyone who belongs to the business; only the owner may change it.\n\nA CUSTOMER MEMBERSHIP HELD BY ANYONE — the owner, a manager, every client the\nshop has — cannot make `is_subscribed` true. The two products are separate\ntables and this reads only its own.","operationId":"subscription_state_v1_businesses__business_id__billing_subscription_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformSubscriptionStateOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/billing/subscriptions":{"post":{"tags":["billing"],"summary":"Start paying MyLook for this business (owner)","description":"Refuses a customer-membership plan with `plan_is_a_customer_membership`.\n\nA professional plan cannot be sold to a consumer either — `POST\n/v1/subscriptions` refuses it with `plan_is_not_a_customer_membership` — and\nunder both endpoints the database would refuse the row regardless.","operationId":"subscribe_v1_businesses__business_id__billing_subscriptions_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformSubscribeIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformSubscriptionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/billing/subscriptions/{subscription_id}/cancel":{"post":{"tags":["billing"],"summary":"Stop it renewing — it runs to period end (owner)","operationId":"cancel_v1_businesses__business_id__billing_subscriptions__subscription_id__cancel_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"subscription_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Subscription Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlatformSubscriptionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/billing/invoices":{"get":{"tags":["billing"],"summary":"What this business has paid MyLook, period by period (owner)","description":"His decision 101: an invoice per paid period, read from the charge that\nlanded in the ledger — never composed. Nothing a client paid the shop is here.","operationId":"invoices_v1_businesses__business_id__billing_invoices_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PlatformInvoiceOut"},"title":"Response Invoices V1 Businesses  Business Id  Billing Invoices Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/professionals":{"get":{"tags":["professionals"],"summary":"Find a professional near you — Discover's Featured Professionals","description":"Public: no sign-in needed. People browse before they have an account.\n\nCross-business, unlike `/businesses/{id}/professionals`: one row per person,\nat their nearest branch, with the shop attached. Carries no money of any kind.","operationId":"search_professionals_v1_professionals_get","parameters":[{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":90,"minimum":-90},{"type":"null"}],"description":"Where the person is. Omitted = no distance, no distance sort.","title":"Lat"},"description":"Where the person is. Omitted = no distance, no distance sort."},{"name":"lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":180,"minimum":-180},{"type":"null"}],"title":"Lng"}},{"name":"radius_miles","in":"query","required":false,"schema":{"type":"number","maximum":200,"exclusiveMinimum":0,"default":10.0,"title":"Radius Miles"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"description":"Name or title","title":"Q"},"description":"Name or title"},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"description":"Category slug of the shop they work at, e.g. barbershop","title":"Category"},"description":"Category slug of the shop they work at, e.g. barbershop"},{"name":"accepting_only","in":"query","required":false,"schema":{"type":"boolean","description":"Only people currently open to new bookings. Off by default: someone paused is still on the platform.","default":false,"title":"Accepting Only"},"description":"Only people currently open to new bookings. Off by default: someone paused is still on the platform."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProfessionalSearchOut"},"title":"Response Search Professionals V1 Professionals Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/professionals/taxonomy/specialties":{"get":{"tags":["professionals"],"summary":"The MyLook specialty taxonomy — his decision 146","description":"Public. What a professional may claim to be good at.\n\nA closed list on purpose: \"MyLook taxonomy... no texto libre como fuente\nprincipal\", and since HIS DECISION 150 a two-level TREE: nine groups and\ntheir children, returned FLAT with each row naming its group so a client\nrenders the tree without a second request.\n\nA group is selectable in its own right. Somebody who does every kind of nail\nwork says Nails; somebody who only does gel says Gel Nails.\n\nAdding an entry is still an INSERT, never a redesign — the same promise the\nprofessions table makes.","operationId":"list_specialties_v1_professionals_taxonomy_specialties_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SpecialtyOut"},"type":"array","title":"Response List Specialties V1 Professionals Taxonomy Specialties Get"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/professionals/taxonomy/languages":{"get":{"tags":["professionals"],"summary":"The languages a professional can be filtered by","description":"Public. His five: English, Spanish, French, Portuguese, Creole.","operationId":"list_languages_v1_professionals_taxonomy_languages_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/malu__domains__professionals__schemas__LanguageOut"},"type":"array","title":"Response List Languages V1 Professionals Taxonomy Languages Get"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/professionals/{professional_id}":{"get":{"tags":["professionals"],"summary":"One professional, with the shop they work at — his decision 71","description":"Public. The read a FAVOURITE needs: it holds the professional's id and\nnothing else. Same conditions as the search — a person at a business that is\nnot active is not public and answers 404 (`professional_not_found`).\n\nONE PROFILE, MANY LOCATIONS (his par.06): `locations` lists every public shop\nthis person works at, the default first — nearest when a position is given,\notherwise the oldest link — and the body's own business and branch fields\nARE that default, or the branch that was asked for. Services, price and\navailability all follow the same location.","operationId":"read_professional_v1_professionals__professional_id__get","parameters":[{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}},{"name":"branch_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"HIS DIRECTIVE 4 par.06 — read the profile IN THIS LOCATION's context. A branch this professional does not publicly work at answers 404 rather than quietly showing another shop's price.","title":"Branch Id"},"description":"HIS DIRECTIVE 4 par.06 — read the profile IN THIS LOCATION's context. A branch this professional does not publicly work at answers 404 rather than quietly showing another shop's price."},{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":90,"minimum":-90},{"type":"null"}],"title":"Lat"}},{"name":"lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":180,"minimum":-180},{"type":"null"}],"title":"Lng"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfessionalSearchOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/professionals/{professional_id}/services":{"get":{"tags":["professionals"],"summary":"What this professional performs, priced at the shop they work at — PRO-PUBLIC-001","description":"Public. HIS DIRECTIVE 3 §12: \"Featured Professional → MlProfessionalCard →\nProfessional Public Profile → Services → Availability → Booking.\" This is the\nprofile's SERVICES step: the professional's active skills, priced by the\ncatalog's rule for the branch they were found at, sorted by name. Same public\nconditions as the read by id — a person at a shop that is not active is\nnobody (404). A skill whose service the branch does not offer is left out,\nbecause it could not be booked there.","operationId":"read_professional_services_v1_professionals__professional_id__services_get","parameters":[{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}},{"name":"branch_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"HIS DIRECTIVE 4 par.06 — what they perform AT THIS LOCATION, at that location's price. Omitted: the default location.","title":"Branch Id"},"description":"HIS DIRECTIVE 4 par.06 — what they perform AT THIS LOCATION, at that location's price. Omitted: the default location."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProfessionalServiceOut"},"title":"Response Read Professional Services V1 Professionals  Professional Id  Services Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/professionals/{professional_id}/reviews":{"get":{"tags":["professionals"],"summary":"What clients said about THIS professional","description":"Public. HIS DECISION 146 — \"Reviews del profesional... deben coincidir con\nprofessional_id. Nunca copiar reviews del negocio.\"\n\nA professional's page had a rating and a review COUNT and no way to read the\nreviews themselves; the only listing on the platform was the business's, and\nshowing that here would credit a person with a shop's work. This reads only\nrows whose `professional_id` is theirs.","operationId":"professional_reviews_v1_professionals__professional_id__reviews_get","parameters":[{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProfessionalPublicReviewOut"},"title":"Response Professional Reviews V1 Professionals  Professional Id  Reviews Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/professionals/{professional_id}/portfolio":{"get":{"tags":["professionals"],"summary":"A professional's work — his decision 59","description":"Public, under the same conditions as the professional themselves: a\nperson at a business that is not active is not public, and neither is their\nwork (404). Only what the professional PUBLISHED (PASO 15 of his directive\nof 2026-09-06: private until explicit publication); Business Only waits for\nhis approval of the three states.","operationId":"read_professional_portfolio_v1_professionals__professional_id__portfolio_get","parameters":[{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PublicPortfolioItemOut"},"title":"Response Read Professional Portfolio V1 Professionals  Professional Id  Portfolio Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/professionals/{professional_id}/portfolio":{"get":{"tags":["professionals"],"summary":"A team member's work as the shop may see it - decision 59, adjustment 08","description":"BUSINESS ONLY, made real: what the professional published plus what they\nshared with the shops they work at. Members of THIS business only, and only\nfor a professional linked to one of its locations; the public route above\nkeeps answering public items alone.","operationId":"read_team_portfolio_v1_businesses__business_id__professionals__professional_id__portfolio_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PublicPortfolioItemOut"},"title":"Response Read Team Portfolio V1 Businesses  Business Id  Professionals  Professional Id  Portfolio Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/portfolio":{"get":{"tags":["professionals"],"summary":"His shop page's Portfolio tab — the team's work, each item naming whose it is","description":"The shop does not own these: each item names the professional who placed\nit, and the shop shows what its team shows. A business that is not public\nhas no public portfolio (empty), exactly as its team is not listed.","operationId":"read_business_portfolio_v1_businesses__business_id__portfolio_get","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PublicPortfolioItemOut"},"title":"Response Read Business Portfolio V1 Businesses  Business Id  Portfolio Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/professionals":{"get":{"tags":["professionals"],"summary":"The professionals of this business","description":"Public. No account ids (his decision 11): the id of the account behind a professional was\nwhat a stranger business needed to take them onto its team.","operationId":"list_professionals_v1_businesses__business_id__professionals_get","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProfessionalOut"},"title":"Response List Professionals V1 Businesses  Business Id  Professionals Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["professionals"],"summary":"Link your own profile, or add a location to a team member's","description":"CR-SEC-2026-09-14-03 — nobody joins a team through this route. An owner links their own\nidentity (his decision 4), or somebody already on the team gets another location (his decision\n7). Anybody else is invited: this answers 409 `invitation_required`.","operationId":"create_professional_v1_businesses__business_id__professionals_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfessionalCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfessionalDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/professionals/{professional_id}":{"get":{"tags":["professionals"],"summary":"One professional","description":"A professional whose relationship with this business ended is no longer one of its team\n(his decision 12), and answers as one it never had.","operationId":"read_professional_v1_businesses__business_id__professionals__professional_id__get","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfessionalDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["professionals"],"summary":"Change the relationship: title here, bookable here","description":"team.manage. The relationship only — `title` and `is_accepting_bookings` at this business\n(his decision 7). The person's own profile is PATCH /me/professional; sending its fields here\nanswers 409 `global_profile_is_the_persons`.","operationId":"update_professional_v1_businesses__business_id__professionals__professional_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfessionalUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfessionalDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/professionals/{professional_id}/end":{"post":{"tags":["professionals"],"summary":"End a professional's relationship with this business","description":"His decision 8 — \"either party may end it\". team.manage, within the caller's reach: a\nlocation-scoped manager ends the relationship at their own location.\n\nWhat ends: the location links, the terms in force there, and the person's PROFESSIONAL role\n— a manager or front desk role they also hold stays. Dated today and kept in the history.\nAppointments are counted in the answer and never moved or cancelled; the person is told.","operationId":"end_professional_v1_businesses__business_id__professionals__professional_id__end_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}}],"requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/RelationshipEndIn"},{"type":"null"}],"title":"Payload"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelationshipEndOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/professionals/{professional_id}/agreements":{"post":{"tags":["professionals"],"summary":"Set the compensation terms (a new version)","operationId":"create_agreement_v1_businesses__business_id__professionals__professional_id__agreements_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgreementCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgreementOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["professionals"],"summary":"Every version of the terms, newest first","operationId":"list_agreements_v1_businesses__business_id__professionals__professional_id__agreements_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AgreementOut"},"title":"Response List Agreements V1 Businesses  Business Id  Professionals  Professional Id  Agreements Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/professionals/{professional_id}/rent-cycles":{"get":{"tags":["professionals"],"summary":"Chair rent: amount, cycle, balance, status","operationId":"list_rent_cycles_v1_businesses__business_id__professionals__professional_id__rent_cycles_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RentCycleOut"},"title":"Response List Rent Cycles V1 Businesses  Business Id  Professionals  Professional Id  Rent Cycles Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/professionals":{"get":{"tags":["professionals","admin"],"summary":"Professionals awaiting a decision — the review queue","description":"Oldest first — it is a queue, and somebody waiting three weeks should not\nbe pushed down the screen by somebody who signed up this morning.","operationId":"review_queue_v1_admin_professionals_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"verified","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"description":"Omit for the queue proper: everybody not yet verified.","title":"Verified"},"description":"Omit for the queue proper: everybody not yet verified."},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"description":"Display name","title":"Q"},"description":"Display name"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProfessionalReviewOut"},"title":"Response Review Queue V1 Admin Professionals Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/professionals/{professional_id}/history":{"get":{"tags":["professionals","admin"],"summary":"Every decision ever taken about this professional","operationId":"history_v1_admin_professionals__professional_id__history_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/VerificationEventOut"},"title":"Response History V1 Admin Professionals  Professional Id  History Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/professionals/{professional_id}/verify":{"post":{"tags":["professionals","admin"],"summary":"Grant a professional's verified tick","description":"Independent of the business tick. Verifying a shop does not verify the\npeople in it, and this does not verify the shop.","operationId":"verify_v1_admin_professionals__professional_id__verify_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffActionIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfessionalOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/professionals/{professional_id}/unverify":{"post":{"tags":["professionals","admin"],"summary":"Withdraw a professional's verified tick","description":"They keep working and keep taking bookings — MyLook simply stops\nvouching for who they are. Whether they accept appointments is theirs\n(`is_accepting_bookings`); whether we vouch for them is ours.","operationId":"unverify_v1_admin_professionals__professional_id__unverify_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffActionIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfessionalOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/money/quote":{"post":{"tags":["money"],"summary":"What a booking will cost, before anything is charged","operationId":"quote_v1_money_quote_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/QuoteOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/money/wallet":{"get":{"tags":["money"],"summary":"Your MyLook credit","operationId":"wallet_v1_money_wallet_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WalletOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/money/wallet/movements":{"get":{"tags":["money"],"summary":"How your credit was earned and spent","operationId":"wallet_movements_v1_money_wallet_movements_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","additionalProperties":true},"title":"Response Wallet Movements V1 Money Wallet Movements Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/money/receipts/{payment_id}":{"get":{"tags":["money"],"summary":"A receipt","operationId":"receipt_v1_money_receipts__payment_id__get","security":[{"BearerAuth":[]}],"parameters":[{"name":"payment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Payment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReceiptOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/money/payments/{payment_id}/refund-preview":{"get":{"tags":["money"],"summary":"What cancelling right now would return, and what it would not","description":"The 24-hour boundary, made visible BEFORE the client commits to it.\n\nThis is the screen that turns \"100% service refund NO significa\nautomáticamente 100% transaction refund\" into something a person can read: it\nnames what comes back, what is retained, and — inside 24 hours — that one\nreschedule is available instead.\n\nIt runs the same resolution the cancellation itself will run, so the two\ncannot disagree. The client's own notice window is read from the appointment,\nnever accepted from the request: a caller who could state the hours could\nstate the refund.","operationId":"refund_preview_v1_money_payments__payment_id__refund_preview_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"payment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Payment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefundPreviewOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/money/payments/{payment_id}/refunds":{"get":{"tags":["money"],"summary":"Every refund decision recorded against a payment","description":"Including decisions that returned nothing. \"Why did I get nothing back?\"\nis exactly the question these rows exist to answer, and a row that is only\nwritten when money moves cannot answer it.","operationId":"payment_refunds_v1_money_payments__payment_id__refunds_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"payment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Payment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RefundOut"},"title":"Response Payment Refunds V1 Money Payments  Payment Id  Refunds Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/money/payments/{payment_id}/refund":{"post":{"tags":["money"],"summary":"Apply an approved refund rule to a payment (MyLook staff)","description":"MyLook's own path — chiefly `mylook_operational`, where the platform is at\nfault and \"100% of every component the client paid is returned\".\n\nStaff-only, and finance-or-admin at that: the automatic cases run themselves\nfrom the booking flow, so anything arriving here is a human overriding what\nthe platform decided, which is precisely the action that should leave a name\non it. `requested_by` records who.\n\nIdempotent by the same UNIQUE key as every other path. Posting this twice\nreturns the FIRST refund and moves nothing — \"el sistema no puede devolver\ndos veces el dinero\" holds for an administrator with a double-clicking mouse\nexactly as it does for a webhook.","operationId":"create_refund_v1_money_payments__payment_id__refund_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"payment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Payment Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefundIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefundOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/money/payments/{payment_id}/refund-requests":{"post":{"tags":["money"],"summary":"Ask for a refund — his decision 102: requesting is not refunding","description":"The payer asks about one of their captured payments. The category routes\nthe question: a business's service or product to that business; a platform\nerror or MyLook's own fee to MyLook's finance staff. Nothing moves here.\nRefused with `not_your_payment` (403), `category_mismatch`, `already_refunded`,\n`payment_not_captured` and `request_already_open` (409).","operationId":"request_refund_v1_money_payments__payment_id__refund_requests_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"payment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Payment Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefundRequestIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefundRequestOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/money/refund-requests/mine":{"get":{"tags":["money"],"summary":"My refund requests, with where each one stands","operationId":"my_refund_requests_v1_money_refund_requests_mine_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/RefundRequestOut"},"type":"array","title":"Response My Refund Requests V1 Money Refund Requests Mine Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/money/refund-requests/{request_id}":{"delete":{"tags":["money"],"summary":"Withdraw my refund request while it is still open","operationId":"withdraw_refund_request_v1_money_refund_requests__request_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefundRequestOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/money/refund-requests":{"get":{"tags":["money"],"summary":"MyLook's refund-request queue — platform errors and its own fee","operationId":"mylook_refund_requests_v1_money_refund_requests_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RefundRequestOut"},"title":"Response Mylook Refund Requests V1 Money Refund Requests Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/money/refund-requests/{request_id}/approve":{"post":{"tags":["money"],"summary":"Approve a refund request — applies the approved rule; the row says what moved","description":"By the authorised party only (`not_your_authority` otherwise). Approval\nrecords reason, actor and moment, then applies the approved rule through the\nrefund engine. The answer is `refunded` with a refund_id when money went\nback with the provider's confirmation, or `approved` with `blocked_reason`\nwhen it could not (no rule for the fee alone — question 126 — or the engine\nrefused).","operationId":"approve_refund_request_v1_money_refund_requests__request_id__approve_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefundRequestDecisionIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefundRequestOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/money/refund-requests/{request_id}/reject":{"post":{"tags":["money"],"summary":"Reject a refund request, with the reason","operationId":"reject_refund_request_v1_money_refund_requests__request_id__reject_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"request_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Request Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefundRequestDecisionIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefundRequestOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/money/penalties/held":{"get":{"tags":["money"],"summary":"Cancellation penalties still held by nobody — should be empty","description":"The screen that proved a decision was outstanding, kept to prove it is not.\n\nThe 2026-08-11 freeze set a 30% penalty for a late cancellation and for a\nno-show and never named who receives it, so every cent was held in ledger\naccount `penalty_holding` — nobody's income, not payable, listed here rather\nthan quietly kept.\n\nHe ruled on 2026-08-12: it belongs to the affected professional, recorded as\nCancellation / No-Show Compensation and not as the income of a completed\nservice. Migration 031 released the accrued balance to them, and refunds now\ncredit them directly. THIS TOTAL SHOULD READ ZERO. A non-zero one is the one\ncase his decision does not reach — a penalty on a payment with no\nprofessional attached — and it is worth a person looking at, which is why the\nroute stays after the decision that created it.","operationId":"penalties_held_v1_money_penalties_held_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":500,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HeldPenaltiesOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/money/earnings/mine":{"get":{"tags":["money"],"summary":"What I made — a professional's own numbers","description":"A professional always sees their own figures in full, whatever their\ncollaboration model — that is the one case the privacy rule never limits.","operationId":"my_earnings_v1_money_earnings_mine_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"date_from","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EarningsOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/money/payouts/mine":{"get":{"tags":["money"],"summary":"My payouts — what has been sent, and what is on its way","operationId":"my_payouts_v1_money_payouts_mine_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PayoutOut"},"title":"Response My Payouts V1 Money Payouts Mine Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/money/owed/mine":{"get":{"tags":["money"],"summary":"What I am owed right now, before any payout","operationId":"my_balance_v1_money_owed_mine_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/OwedOut"},{"type":"null"}],"title":"Response My Balance V1 Money Owed Mine Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/money/disputes":{"get":{"tags":["money"],"summary":"Chargebacks, and who bore each one (MyLook staff)","operationId":"list_disputes_v1_money_disputes_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/DisputeOut"},"title":"Response List Disputes V1 Money Disputes Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/money/disputes/{dispute_id}/liability":{"get":{"tags":["money"],"summary":"What losing this chargeback would cost each party","description":"The economic origin of the transaction, made readable BEFORE anything is\nborne — and afterwards, unchanged, because it is read from the same ledger.\n\nIt runs the same resolution the settlement runs, so what a staff member is\nshown and what then happens cannot disagree. `unattributed_cents` is the\nfield worth looking at: non-zero means part of this chargeback was received\nby nobody who can bear it, and the platform will NOT quietly absorb the\ndifference — that is the outcome the owner ruled out by name.","operationId":"dispute_liability_v1_money_disputes__dispute_id__liability_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"dispute_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dispute Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputeLiabilityPreviewOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/money/disputes/{dispute_id}/accept-liability":{"post":{"tags":["money"],"summary":"MyLook accepts the loss on this chargeback (MyLook staff)","description":"His third case: \"Error directamente atribuible a MyLook/plataforma: MyLook\ndebe poder asumir la responsabilidad correspondiente.\"\n\nPODER ASUMIR — be able to assume it. A capability given to a person, not a\nfallback the code reaches for, which is why this is a route and not a branch.\n`reason` is required, stored verbatim, and the staff member's id goes on the\nrow; 036 refuses a platform liability with neither at the database, so this\ncannot be gone around by another writer.\n\nNothing moves here. A dispute may be accepted while it is still under review\nand may still be WON, in which case no money was taken and nobody bears\nanything. The entries are posted when the processor says it was lost.","operationId":"accept_dispute_liability_v1_money_disputes__dispute_id__accept_liability_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"dispute_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Dispute Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptLiabilityIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DisputeOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/money/webhooks/events":{"get":{"tags":["money"],"summary":"Recent processor events — reconciliation and dead letters","description":"Staff only. This is the reconciliation surface the audit asked for: what\narrived, what was acted on, and what failed and is waiting for a person.","operationId":"list_webhook_events_v1_money_webhooks_events_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEventOut"},"title":"Response List Webhook Events V1 Money Webhooks Events Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/refund-requests":{"get":{"tags":["money"],"summary":"The business's refund-request queue — his decision 102","description":"Requests about this business's services and products. finance.view_business\n— whoever may see the shop's money may decide on giving it back.","operationId":"business_refund_requests_v1_businesses__business_id__refund_requests_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/RefundRequestOut"},"title":"Response Business Refund Requests V1 Businesses  Business Id  Refund Requests Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/earnings":{"get":{"tags":["money"],"summary":"What the shop made","description":"The owner's share of services, plus chair rent collected.\n\nA chair-rent professional's own takings are absent, by the client's rule: they\nare not the shop's money. What the shop is owed is the rent, and it is here.\nThe response says so rather than leaving a silent hole in the arithmetic.","operationId":"business_earnings_v1_businesses__business_id__earnings_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"date_from","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Date From"}},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date To"}},{"name":"branch_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EarningsOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/payouts":{"get":{"tags":["money"],"summary":"The shop's payouts","operationId":"business_payouts_v1_businesses__business_id__payouts_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PayoutOut"},"title":"Response Business Payouts V1 Businesses  Business Id  Payouts Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/payouts/account":{"get":{"tags":["money"],"summary":"This shop's payout account and what it still needs","operationId":"get_payout_account_v1_businesses__business_id__payouts_account_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectedAccountOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["money"],"summary":"Start payout setup for this shop","description":"Only the owner. Deciding where a business's money lands is not something\na manager or the front desk does, and it is not undoable by them either.","operationId":"create_payout_account_v1_businesses__business_id__payouts_account_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConnectedAccountOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/payouts/account/link":{"post":{"tags":["money"],"summary":"A link to finish payout setup","operationId":"payout_onboarding_link_v1_businesses__business_id__payouts_account_link_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OnboardingLinkOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/webhooks/stripe":{"post":{"tags":["money","webhooks"],"summary":"Inbound events from the payment processor","description":"NOT authenticated by a bearer token — authenticated by a SIGNATURE.\n\nThat is the whole security model here and it is deliberate: the caller is a\nprocessor, not a person, and it holds a shared secret rather than an\naccount. `security` is therefore absent from this operation in the contract,\nwhich is correct and not an oversight.\n\nThe RAW body is what gets verified. Reading it as parsed JSON and\nre-serialising changes the bytes — key order, whitespace — and the signature\nthen fails for every legitimate event, which is a very confusing morning.","operationId":"stripe_webhook_v1_webhooks_stripe_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Stripe Webhook V1 Webhooks Stripe Post"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/reviews/attributes":{"get":{"tags":["engagement"],"summary":"The chips a client may tap","description":"His decision 28's vocabulary, served rather than hardcoded.\n\nPUBLIC, and before the review routes that take an id — \"/attributes\" would\notherwise be matched as a review id and fail as a bad UUID. It needs no\nsession: the chips are the same six for everybody, and the screen that\ndraws them is reachable before a review exists.","operationId":"review_attributes_v1_reviews_attributes_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ReviewAttributeOut"},"type":"array","title":"Response Review Attributes V1 Reviews Attributes Get"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/reviews":{"post":{"tags":["engagement"],"summary":"Review a completed appointment","operationId":"create_review_v1_reviews_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewCreateIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/reviews/mine":{"get":{"tags":["engagement"],"summary":"Reviews I've left","operationId":"my_reviews_v1_reviews_mine_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ReviewOut"},"type":"array","title":"Response My Reviews V1 Reviews Mine Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/reviews/{review_id}":{"patch":{"tags":["engagement"],"summary":"Correct my own review — his decision 31","description":"The author fixes what they wrote.\n\nTHE PREVIOUS TEXT IS KEPT. His decision 30 requires history and audit on\nevery edit, so a shop that replied to a five-star review which has since\nbecome a one-star review can show what it was replying to.\n\nThe seven-day window his decision 30 recommends is a PENDING value and\nnothing is built on it: refusing an edit on the eighth day would be\nenforcing a rule he has not approved. See moderation.EDIT_WINDOW.","operationId":"edit_review_v1_reviews__review_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Review Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewEditIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true},"delete":{"tags":["engagement"],"summary":"Take my own review down — his decision 31","description":"WITHDRAW, NOT DELETE, which is why his own wording pairs the two.\n\nThe row stays: the appointment is still reviewed, so `appointment_id` being\nUNIQUE still means what it says, and nobody can withdraw a one-star review\nand write a fresh one an hour later. It leaves the public listing and the\nshop's rating immediately.","operationId":"withdraw_review_v1_reviews__review_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Review Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/reviews/{review_id}/report":{"post":{"tags":["engagement"],"summary":"Report a review — his decisions 31 and 17","description":"Anybody signed in may report one.\n\nReporting the same review twice returns the first report rather than\nrefusing: a person who taps it again has not done something wrong, and five\nreports from one person are not five times the signal. The moderation queue\ncounts DISTINCT reporters.","operationId":"report_review_v1_reviews__review_id__report_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Review Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewReportIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewReportOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/reviews/{review_id}/media-consent":{"put":{"tags":["engagement"],"summary":"Allow — or stop allowing — this business to use my photos","description":"His decision 29 and his pantalla's Revoke Permission.\n\nThe author's alone: a business that could grant itself this would make the\nword consent meaningless.","operationId":"media_consent_v1_reviews__review_id__media_consent_put","security":[{"BearerAuth":[]}],"parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Review Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaConsentIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/reviews/{review_id}/respond":{"post":{"tags":["engagement"],"summary":"Reply to a review (once, as the business)","operationId":"respond_to_review_v1_reviews__review_id__respond_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Review Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewResponseIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewResponseOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/admin/moderation/reviews":{"get":{"tags":["trust-and-safety"],"summary":"Reported reviews, worst first","description":"ORDERED BY DISTINCT REPORTERS, then by age.\n\nTen people reporting one review is a different fact from one person\nreporting ten, and a queue that sorts only by time cannot tell them apart —\nwhich is the same reasoning behind his decision 99 for the support queue.","operationId":"review_queue_v1_admin_moderation_reviews_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ModerationQueueItemOut"},"title":"Response Review Queue V1 Admin Moderation Reviews Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/moderation/reviews/{review_id}":{"post":{"tags":["trust-and-safety"],"summary":"Decide — remove, restore, or keep","description":"One decision answers every open report on that review.\n\n`removed` takes it out of public view and tells the BUSINESS that it\nhappened, with a date and the general reason — his decision 36 — while the\ninternal note stays with MyLook. `kept` closes the reports without touching\nthe review, which is the answer most reports deserve.","operationId":"moderate_review_v1_admin_moderation_reviews__review_id__post","security":[{"BearerAuth":[]}],"parameters":[{"name":"review_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Review Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ModerateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/conversations":{"post":{"tags":["engagement"],"summary":"A shop starts the conversation (owner question 66)","description":"Threads used to be CLIENT-INITIATED ONLY: a shop could reply and never\nwrite first, so his shop-side compose button and his \"Message the client\" on\nan order had nothing behind them.\n\nFind-or-create on the same (location, client) row the client's own door uses,\nso a shop writing to somebody who already wrote lands in the history rather\nthan beside it. A shop may write to a client who has BOOKED OR BOUGHT from\nit — the rule is where his buttons are, and without it this would be a way to\nmessage any account whose id a shop happens to know.","operationId":"shop_opens_conversation_v1_businesses__business_id__conversations_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShopConversationOpenIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/reviews":{"get":{"tags":["engagement"],"summary":"What clients said","operationId":"list_business_reviews_v1_businesses__business_id__reviews_get","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PublicReviewOut"},"title":"Response List Business Reviews V1 Businesses  Business Id  Reviews Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/reviews/inbox":{"get":{"tags":["engagement"],"summary":"The business's reviews, with who wrote them (team.view)","operationId":"review_inbox_v1_businesses__business_id__reviews_inbox_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"needs_reply","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Needs Reply"}},{"name":"is_new","in":"query","required":false,"schema":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is New"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ReviewInboxItemOut"},"title":"Response Review Inbox V1 Businesses  Business Id  Reviews Inbox Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/reviews/metrics":{"get":{"tags":["engagement"],"summary":"Rating trend, response rate, response time, volume","description":"His decision 34 — the four governed metrics, computed in one place.\n\nAnyone who can see the team can read them, the same gate as the inbox they\ndescribe. Each number arrives with its definition and its lineage, so the\nscreen shows what it counts rather than asserting a figure.","operationId":"review_metrics_v1_businesses__business_id__reviews_metrics_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"months","in":"query","required":false,"schema":{"type":"integer","default":6,"title":"Months"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewMetricsOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/reviews/attribute-tally":{"get":{"tags":["engagement"],"summary":"How often each chip was tapped","operationId":"attribute_tally_v1_businesses__business_id__reviews_attribute_tally_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"months","in":"query","required":false,"schema":{"type":"integer","default":6,"title":"Months"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AttributeTallyOut"},"title":"Response Attribute Tally V1 Businesses  Business Id  Reviews Attribute Tally Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/review-requests/templates":{"get":{"tags":["engagement"],"summary":"The wordings this business has saved","operationId":"list_templates_v1_businesses__business_id__review_requests_templates_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ReviewRequestTemplateOut"},"title":"Response List Templates V1 Businesses  Business Id  Review Requests Templates Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["engagement"],"summary":"Save a wording","operationId":"create_template_v1_businesses__business_id__review_requests_templates_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewRequestTemplateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewRequestTemplateOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/review-requests/templates/{template_id}":{"patch":{"tags":["engagement"],"summary":"Change a wording","description":"Every field is optional and None means LEAVE IT ALONE — not \"clear it\".\n\nWorth saying out loud because the opposite reading is what broke PUT\n/social, where a payload naming one platform wiped the other four. Here the\nservice checks `is not None` before writing, so a body that sends only\n`name` changes only the name.","operationId":"update_template_v1_businesses__business_id__review_requests_templates__template_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewRequestTemplateUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewRequestTemplateOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["engagement"],"summary":"Retire a wording","operationId":"archive_template_v1_businesses__business_id__review_requests_templates__template_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"template_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Template Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/review-requests":{"post":{"tags":["engagement"],"summary":"Ask a client how a visit went","description":"His decision 35's Send Review Request — a real notification, once.","operationId":"send_review_request_v1_businesses__business_id__review_requests_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewRequestIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReviewRequestOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["engagement"],"summary":"Who was asked, and who answered","operationId":"list_review_requests_v1_businesses__business_id__review_requests_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","default":50,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ReviewRequestOut"},"title":"Response List Review Requests V1 Businesses  Business Id  Review Requests Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/automations":{"get":{"tags":["engagement"],"summary":"His three automations, and the one with business configuration","operationId":"business_automations_v1_businesses__business_id__automations_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationsOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["engagement"],"summary":"Review Request: on or off, and how long after the visit","description":"BUSINESS_EDIT. Booking Confirmation and the 24-hour Reminder have no\nswitch: they affect an appointment and his decision 14 says they cannot be\ndisabled.","operationId":"update_business_automations_v1_businesses__business_id__automations_patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationsIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AutomationsOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/rating":{"get":{"tags":["engagement"],"summary":"The stored rating aggregate","description":"Read, not recomputed: `businesses.rating_avg` / `rating_count` are written\nwhen a review is created, so discovery can sort by them cheaply.","operationId":"business_rating_v1_businesses__business_id__rating_get","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RatingSummaryOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/favorites":{"get":{"tags":["engagement"],"summary":"What I've saved","operationId":"list_favorites_v1_favorites_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"kind","in":"query","required":false,"schema":{"anyOf":[{"$ref":"#/components/schemas/FavoriteKind"},{"type":"null"}],"title":"Kind"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/FavoriteOut"},"title":"Response List Favorites V1 Favorites Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["engagement"],"summary":"Save a business, professional or service","description":"A toggle, so saving twice is not an error — the app never has to know whether\nit already saved this one.","operationId":"add_favorite_v1_favorites_post","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FavoriteIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/FavoriteOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/favorites/{kind}/{target_id}":{"delete":{"tags":["engagement"],"summary":"Remove a saved item","operationId":"remove_favorite_v1_favorites__kind___target_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"kind","in":"path","required":true,"schema":{"$ref":"#/components/schemas/FavoriteKind"}},{"name":"target_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Target Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/referrals":{"post":{"tags":["engagement"],"summary":"Invite a salon or a friend","description":"Creates a PENDING invitation worth 0. The reward is earned when it converts,\nnot when it is sent — inviting the same target again returns the same invitation.","operationId":"create_referral_v1_referrals_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferralCreateIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReferralOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/referrals/mine":{"get":{"tags":["engagement"],"summary":"My invitations and where they stand","operationId":"my_referrals_v1_referrals_mine_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ReferralOut"},"type":"array","title":"Response My Referrals V1 Referrals Mine Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/conversations":{"post":{"tags":["engagement"],"summary":"Open the thread with a location","description":"Find-or-create: one thread per (location, client), so the history is never\nsplit across duplicates.","operationId":"open_conversation_v1_conversations_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationOpenIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ConversationOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/conversations/mine":{"get":{"tags":["engagement"],"summary":"My threads","operationId":"my_conversations_v1_conversations_mine_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/ConversationOut"},"type":"array","title":"Response My Conversations V1 Conversations Mine Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/conversations/{conversation_id}/messages":{"get":{"tags":["engagement"],"summary":"Messages, newest first","operationId":"list_messages_v1_conversations__conversation_id__messages_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Conversation Id"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}},{"name":"before","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"description":"Page back from this message id","title":"Before"},"description":"Page back from this message id"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/malu__domains__engagement__schemas__MessageOut"},"title":"Response List Messages V1 Conversations  Conversation Id  Messages Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true},"post":{"tags":["engagement"],"summary":"Send a message","operationId":"send_message_v1_conversations__conversation_id__messages_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Conversation Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__engagement__schemas__MessageIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__engagement__schemas__MessageOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/conversations/{conversation_id}/read":{"post":{"tags":["engagement"],"summary":"I have seen this thread — the other side's messages are read","description":"Question 37. `read_at` existed since 007 and nothing wrote it, so no inbox\non the platform could count what was unread. Marks the OTHER side's messages;\nanswers how many, so a repeat answers 0.","operationId":"read_conversation_v1_conversations__conversation_id__read_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"conversation_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Conversation Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Read Conversation V1 Conversations  Conversation Id  Read Post"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/notifications":{"get":{"tags":["engagement"],"summary":"My notifications","operationId":"list_notifications_v1_notifications_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"unread_only","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Unread Only"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/NotificationOut"},"title":"Response List Notifications V1 Notifications Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/notifications/preferences":{"get":{"tags":["engagement"],"summary":"What I want to be told, and how","description":"Owner question 44, and the half of his decision 39 that had no control.\n\nA PREFERENCE GOVERNS DELIVERY, NEVER THE RECORD — the answer says so, on the\nscreen, rather than leaving somebody to find out that turning reminders off\nalso emptied their inbox. It does not.","operationId":"notification_preferences_v1_notifications_preferences_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"put":{"tags":["engagement"],"summary":"Change them","operationId":"save_notification_preferences_v1_notifications_preferences_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationPreferencesOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/notifications/read-all":{"post":{"tags":["engagement"],"summary":"Mark everything as read","operationId":"read_all_v1_notifications_read_all_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Read All V1 Notifications Read All Post"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/notifications/{notification_id}/read":{"post":{"tags":["engagement"],"summary":"Mark one as read","operationId":"read_notification_v1_notifications__notification_id__read_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"notification_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Notification Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/device-tokens":{"post":{"tags":["engagement"],"summary":"Register for push","operationId":"register_device_token_v1_device_tokens_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceTokenIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeviceTokenOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/onboarding":{"get":{"tags":["onboarding"],"summary":"This person's roles, their journey, and where they stopped","description":"One call on launch answers all three questions the app has: who did they\nsay they are, which screens do they owe, and where were they.","operationId":"read_onboarding_v1_me_onboarding_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JourneyOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/onboarding/roles":{"put":{"tags":["onboarding"],"summary":"How will you use MyLook? — his ONB-004","description":"Replace the role set, and answer with the journey it produces.\n\nAdding a role months later comes through here too — \"Los roles deben poder\nagregarse posteriormente\" — and the answer is the same shape, so the app\nneeds no second path for it.\n\nThe reply carries `steps` because the set and the journey change together:\na client who adds `professional` gains five screens in that instant, and the\napp should not have to work that out for itself.","operationId":"set_roles_v1_me_onboarding_roles_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RolesIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JourneyOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/onboarding/draft":{"put":{"tags":["onboarding"],"summary":"Save & Exit — keep what they have typed","description":"Auto-save. Called when a step is left, not on a clock.\n\nNothing final lives here — by the time a screen is left its real data is\nalready in `users`, `professionals` or `businesses`. This holds what is\nstill in flight, so a train going into a tunnel does not cost somebody a\nphoto, a bio and an address.","operationId":"save_draft_v1_me_onboarding_draft_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DraftIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JourneyOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/onboarding/complete":{"post":{"tags":["onboarding"],"summary":"MyLook Ready — his ONB-015","description":"Reaching the end. The draft is kept, not deleted: \"did this person finish,\nand how long did it take\" should be answerable from the database.","operationId":"complete_v1_me_onboarding_complete_post","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/JourneyOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/onboarding/personalization":{"get":{"tags":["onboarding"],"summary":"His ONB-008 — three questions, filtered by role","description":"The questions AND what this person has already answered, in one read.\n\nTogether because the screen needs both to draw itself, and two calls would\nlet it render an un-ticked chip for half a frame.","operationId":"get_personalization_v1_me_onboarding_personalization_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalizationOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"put":{"tags":["onboarding"],"summary":"Save his ONB-008 answers","operationId":"save_personalization_v1_me_onboarding_personalization_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalizationIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PersonalizationOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/professions":{"get":{"tags":["professionals"],"summary":"What do you do? — his ONB-005 grid, and his §15 eight","description":"His thirteen, from the database rather than a constant in the app.\n\n\"La arquitectura debe soportar nuevas profesiones sin rediseñar la pantalla.\" A fourteenth\nprofession is an INSERT and the grid gains a tile.\n\nAND TWO SCREENS ASK DIFFERENT QUESTIONS OF THE SAME TABLE. ONB-005 offers everything MyLook\nrecognises; his registration offers the EIGHT of his §15 and deliberately not Other, because\n\"esto protege el alcance actual de MyLook como plataforma de Beauty\". Which rows belong to\nwhich screen is marked on the table (migration 106), not decided here and not in the app.","operationId":"list_professions_v1_me_professions_get","parameters":[{"name":"for_registration","in":"query","required":false,"schema":{"type":"boolean","description":"His PROFESSIONAL REGISTRATION v1.3 §15: the EIGHT his sign-up offers, in his order, with no Other. Off, the whole taxonomy - ONB-005's thirteen.","default":false,"title":"For Registration"},"description":"His PROFESSIONAL REGISTRATION v1.3 §15: the EIGHT his sign-up offers, in his order, with no Other. Off, the whole taxonomy - ONB-005's thirteen."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProfessionOut"},"title":"Response List Professions V1 Me Professions Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/professional/professions":{"get":{"tags":["professionals"],"summary":"What I do","operationId":"read_own_professions_v1_me_professional_professions_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyProfessionsOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"put":{"tags":["professionals"],"summary":"Set what I do — multi-select, first is primary","description":"Multi-select, and the FIRST slug is the primary one.\n\nThe order of the list carries which is primary rather than a separate flag,\nso the app cannot get out of step with the badge it drew on screen.","operationId":"set_own_professions_v1_me_professional_professions_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfessionsIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyProfessionsOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/professional":{"get":{"tags":["professionals"],"summary":"My own professional identity","description":"What ONB-009 pre-fills from and what ONB-014 previews.\n\nThere is no public read for a professional yet — the detail endpoint is\nscoped to a business, which an independent professional does not have. This\nis the person reading their own, which is what onboarding needs; a public\nprofessional page is its own screen and its own decision.","operationId":"read_own_professional_v1_me_professional_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfessionalOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"post":{"tags":["professionals"],"summary":"Become a professional, with or without a shop","description":"His ONB-009, for somebody who owns nothing.\n\nA barber who rents a chair and a stylist who travels are professionals with\nno business, and his Professional path has no business step in it. Until\nnow the only way to create a professional required a `branch_id`, so an\nindependent one had to invent a shop — which would then be a real shop in\nDiscover, in search and in the ledger.\n\nAn unaffiliated professional is NOT bookable, and that needs no new rule:\navailability joins through branches and services, so no branch means no\nhours and no slots. They have a profile, a portfolio and a public page.\nJoining or creating a shop later adds the link to the SAME profile.\n\nCalling this twice returns the existing profile rather than failing — that\nis a person tapping Continue twice, not an error worth a screen.","operationId":"create_own_professional_v1_me_professional_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OwnProfessionalIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfessionalOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"patch":{"tags":["professionals"],"summary":"Edit my own professional profile","description":"CR-SEC-2026-09-14-03, his decision 7 — \"global professional identity belongs primarily to\nthe person.\"\n\nThe name, photo, bio, years, specialties and languages that every business shows are written\nhere, by the person, and by nobody else: a business may change only its own relationship with\nthem. `is_accepting_bookings` is the person's GLOBAL switch — off, and they are bookable at no\nbusiness.","operationId":"update_own_professional_v1_me_professional_patch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfessionalUpdateIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfessionalOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/professional/social":{"get":{"tags":["professionals"],"summary":"My social presence","operationId":"read_own_social_v1_me_professional_social_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SocialLinkOut"},"type":"array","title":"Response Read Own Social V1 Me Professional Social Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"put":{"tags":["professionals"],"summary":"Connect your presence — his ONB-012","description":"Optional, always. A pasted profile URL is accepted and reduced to a\nhandle rather than refused — pasting the address bar is what people do.","operationId":"set_own_social_v1_me_professional_social_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SocialLinksIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/SocialLinkOut"},"type":"array","title":"Response Set Own Social V1 Me Professional Social Put"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/professional/work-setups":{"get":{"tags":["professionals"],"summary":"How I work — MY PROFILE v1.1 section 2","description":"Mine, in my own order, every status: a professional's list is their history too.","operationId":"read_own_work_setups_v1_me_professional_work_setups_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/WorkSetupOut"},"type":"array","title":"Response Read Own Work Setups V1 Me Professional Work Setups Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]},"post":{"tags":["professionals"],"summary":"Add a way of working — one row per place; several ARE his Multiple Work Locations","operationId":"add_own_work_setup_v1_me_professional_work_setups_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkSetupIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkSetupOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/professional/work-setups/{setup_id}":{"patch":{"tags":["professionals"],"summary":"Change how I work, or publish it","description":"Only what is sent changes, and the whole row is checked afterwards: his rules are about the\nrow as it WILL be, not about the fields that happened to arrive.","operationId":"update_own_work_setup_v1_me_professional_work_setups__setup_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"setup_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Setup Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkSetupPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WorkSetupOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/professional/portfolio":{"get":{"tags":["professionals"],"summary":"My portfolio — his ONB-013","operationId":"read_own_portfolio_v1_me_professional_portfolio_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"section","in":"query","required":false,"schema":{"anyOf":[{"enum":["my_work","my_business","my_space","my_team","before_after"],"type":"string"},{"type":"null"}],"title":"Section"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PortfolioItemOut"},"title":"Response Read Own Portfolio V1 Me Professional Portfolio Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["professionals"],"summary":"Add a photo to my portfolio","description":"The upload already happened — that is media's job. This is where the\nperson put it.","operationId":"add_own_portfolio_v1_me_professional_portfolio_post","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortfolioItemIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortfolioItemOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/professional/portfolio/order":{"put":{"tags":["professionals"],"summary":"The order they dragged the tiles into","operationId":"reorder_own_portfolio_v1_me_professional_portfolio_order_put","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReorderIn"}}},"required":true},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/PortfolioItemOut"},"type":"array","title":"Response Reorder Own Portfolio V1 Me Professional Portfolio Order Put"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/professional/portfolio/{item_id}/cover":{"put":{"tags":["professionals"],"summary":"Set as cover — one per portfolio","operationId":"set_own_cover_v1_me_professional_portfolio__item_id__cover_put","security":[{"BearerAuth":[]}],"parameters":[{"name":"item_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Item Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortfolioItemOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/professional/portfolio/{item_id}/visibility":{"put":{"tags":["professionals"],"summary":"Publish a photo, or take it back (PASO 15)","description":"A photo is private until its owner says otherwise - his directive of\n2026-09-06. Three states since his adjustment 08 the same day: private (the\nowner), business_only (the owner and the shops they work at), public.","operationId":"set_own_visibility_v1_me_professional_portfolio__item_id__visibility_put","security":[{"BearerAuth":[]}],"parameters":[{"name":"item_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Item Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/VisibilityIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PortfolioItemOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/professional/portfolio/{item_id}":{"delete":{"tags":["professionals"],"summary":"Take a photo out of my portfolio","description":"The FILE is untouched. Somebody removing a picture from a grid has not\nasked for it to be destroyed.","operationId":"remove_own_portfolio_v1_me_professional_portfolio__item_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"item_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Item Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/directory/ingest":{"post":{"tags":["directory"],"summary":"Upsert a harvested batch (machine-to-machine)","description":"Idempotent on (source, source_ref). Re-running the same batch updates the\nsame rows; it never duplicates them, and it never touches a claimed listing.","operationId":"ingest_v1_directory_ingest_post","parameters":[{"name":"x-directory-key","in":"header","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"X-Directory-Key"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestBatchIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IngestResultOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/directory/search":{"get":{"tags":["directory"],"summary":"Unclaimed listings near a point, nearest first","operationId":"search_v1_directory_search_get","parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","maximum":90,"minimum":-90,"description":"Latitude of the search centre","title":"Lat"},"description":"Latitude of the search centre"},{"name":"lng","in":"query","required":true,"schema":{"type":"number","maximum":180,"minimum":-180,"description":"Longitude of the search centre","title":"Lng"},"description":"Longitude of the search centre"},{"name":"radius_miles","in":"query","required":false,"schema":{"type":"number","maximum":200,"exclusiveMinimum":0,"default":10,"title":"Radius Miles"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Q"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ListingSearchOut"},"title":"Response Search V1 Directory Search Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/directory/{listing_id}":{"get":{"tags":["directory"],"summary":"One listing, with a preview of the page it could have","description":"A harvested listing is a name, an address and a phone number, and drawn as\nthose three facts it reads like a dead end.\n\nSo it carries a PREVIEW: the services and products a shop of its kind\nactually offers on MyLook, so a barber sent this link sees the page he would\nget rather than a row in a database. Every figure is the median across real\nbusinesses in the same category, and `preview.is_example` is set by the\nserver — this is what a page like yours looks like, never what this shop\ncharges. See directory/preview.py for why that line is not negotiable.","operationId":"read_listing_v1_directory__listing_id__get","parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Listing Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ListingDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/directory/{listing_id}/claim":{"post":{"tags":["directory"],"summary":"Claim this listing as its owner","description":"Evidence is a list of object-storage KEYS for documents already uploaded.\nNo file bytes ever reach this endpoint.","operationId":"claim_listing_v1_directory__listing_id__claim_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"listing_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Listing Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/directory/claims":{"get":{"tags":["directory","admin"],"summary":"The claim review queue","description":"Evidence is returned as storage KEYS only — the documents themselves are\nfetched from object storage, deliberately and audibly, never inlined here.","operationId":"list_claims_v1_admin_directory_claims_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"enum":["pending","auto_approved","approved","rejected","superseded","all"],"type":"string","default":"pending","title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":100,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ClaimReviewOut"},"title":"Response List Claims V1 Admin Directory Claims Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/directory/claims/{claim_id}/approve":{"post":{"tags":["directory","admin"],"summary":"Approve a claim and convert the listing into a business","operationId":"approve_claim_v1_admin_directory_claims__claim_id__approve_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"claim_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Claim Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimReviewOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/admin/directory/claims/{claim_id}/reject":{"post":{"tags":["directory","admin"],"summary":"Turn a claim down and put the listing back on the map","operationId":"reject_claim_v1_admin_directory_claims__claim_id__reject_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"claim_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Claim Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimRejectIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClaimReviewOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/booking/availability":{"get":{"tags":["booking"],"summary":"Open slots for a service on one day","description":"Public — no sign-in. Leave `professional_id` out to see everyone at that location\nwho can perform the service; each slot says whose it is.","operationId":"availability_v1_booking_availability_get","parameters":[{"name":"branch_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Branch Id"}},{"name":"service_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Service Id"}},{"name":"date","in":"query","required":true,"schema":{"type":"string","format":"date","description":"Local to the branch","title":"Date"},"description":"Local to the branch"},{"name":"professional_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Professional Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvailabilityOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/booking/appointments":{"post":{"tags":["booking"],"summary":"Book a slot","description":"Creates the appointment as `pending_payment` with the price, duration and name\nfrozen onto it. Money confirms it from there. With an `Idempotency-Key`, a\ndouble tap, a network retry or a replay returns the original booking.","operationId":"create_appointment_v1_booking_appointments_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"description":"HIS DIRECTIVE 3 §27 — send one per booking attempt and keep it across retries: the same key from the same person is answered with the SAME appointment, never a second one.","title":"Idempotency-Key"},"description":"HIS DIRECTIVE 3 §27 — send one per booking attempt and keep it across retries: the same key from the same person is answered with the SAME appointment, never a second one."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/booking/appointments/mine":{"get":{"tags":["booking"],"summary":"Your appointments, with the shop and the professional","operationId":"my_appointments_v1_booking_appointments_mine_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"enum":["upcoming","past","cancelled"],"type":"string"},{"type":"null"}],"title":"Status"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MyAppointmentOut"},"title":"Response My Appointments V1 Booking Appointments Mine Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/booking/appointments/{appointment_id}":{"get":{"tags":["booking"],"summary":"One appointment, with its timeline","description":"The client's own, or the shop's — scoped and masked as the agenda is.","operationId":"read_appointment_v1_booking_appointments__appointment_id__get","security":[{"BearerAuth":[]}],"parameters":[{"name":"appointment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Appointment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/booking/appointments/{appointment_id}/professional-note":{"patch":{"tags":["booking"],"summary":"The shop's internal note on a booking — his 'Professional Notes (Internal)'","description":"schedule.edit at that location. Empty clears. The client never reads it.","operationId":"set_professional_note_v1_booking_appointments__appointment_id__professional_note_patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"appointment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Appointment Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfessionalNoteIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/booking/appointments/{appointment_id}/cancel":{"patch":{"tags":["booking"],"summary":"Cancel (either side)","description":"The client's cancellation and the shop's are recorded as different events —\nMoney's refund rules read that difference.","operationId":"cancel_appointment_v1_booking_appointments__appointment_id__cancel_patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"appointment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Appointment Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CancelIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/booking/appointments/{appointment_id}/running-late":{"post":{"tags":["booking"],"summary":"I'm running late — his §23 and §24","description":"HIS §24, from the client's own app — or from the shop, when somebody rings instead.\n\nIt records what was said and nothing else: the booking keeps its time and its status, and\navailability is untouched. His §25's preview travels with it; the conversation stays in\nMessaging.","operationId":"report_running_late_v1_booking_appointments__appointment_id__running_late_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"appointment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Appointment Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunningLateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BookingUpdateOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/booking/appointments/{appointment_id}/reschedule":{"patch":{"tags":["booking"],"summary":"Move a booking — the client's ONE reschedule","description":"The freeze's alternative to a late cancellation, and the only way to reach\nit. `booking.reschedule_appointment` existed and passed its tests while\nnothing exposed it, so the entitlement the owner granted in §8 could not be\nused by anybody holding a booking.\n\nONE, and subject to availability — both enforced below rather than here:\nUNIQUE (appointment_id) on appointment_reschedules, because a counter in\napplication code is a counter two concurrent requests both read as zero, and\nthe same availability pass every new booking goes through.\n\nNo money moves. The booking keeps the payment it already made, which is the\nwhole point of offering this instead of the 70% refund.","operationId":"reschedule_appointment_v1_booking_appointments__appointment_id__reschedule_patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"appointment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Appointment Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RescheduleIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/booking/appointments/{appointment_id}/move":{"post":{"tags":["booking"],"summary":"The shop asks to move a booking — his decision 79","description":"A PROPOSAL, not a move: the booking's time does not change until the client\naccepts (`pending_move` on the answer says what is being asked). Requires\nschedule.edit at that location. Refused with `not_movable` (not a confirmed\nbooking), `slot_in_the_past`, `same_time` and `slot_unavailable` — the shop\nis told at once, not when the client taps Accept. A second proposal\nsupersedes the first.\n\nA guest booking (his decision 12 — no account to ask) is moved at once and\nthe answer carries no `pending_move`.","operationId":"propose_move_v1_booking_appointments__appointment_id__move_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"appointment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Appointment Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MoveProposeIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true},"delete":{"tags":["booking"],"summary":"The shop withdraws its request to move","operationId":"withdraw_move_v1_booking_appointments__appointment_id__move_delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"appointment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Appointment Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/booking/appointments/{appointment_id}/move/{proposal_id}/accept":{"post":{"tags":["booking"],"summary":"The client accepts the shop's move","description":"Only the client who holds the booking (`not_the_client` for a member of the\nshop). Subject to availability NOW — a proposal never held the slot — so\n`slot_unavailable` here means the request lapsed and the shop is told to ask\nagain. The client's own ONE reschedule is untouched by this.","operationId":"accept_move_v1_booking_appointments__appointment_id__move__proposal_id__accept_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"appointment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Appointment Id"}},{"name":"proposal_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Proposal Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/booking/appointments/{appointment_id}/move/{proposal_id}/decline":{"post":{"tags":["booking"],"summary":"The client declines the shop's move","operationId":"decline_move_v1_booking_appointments__appointment_id__move__proposal_id__decline_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"appointment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Appointment Id"}},{"name":"proposal_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Proposal Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/booking/appointments/{appointment_id}/status":{"patch":{"tags":["booking"],"summary":"Move an appointment along (business side)","description":"Confirm, start, finish, or record a no-show. Requires schedule.edit at that\nlocation, and every move writes an appointment_events row.","operationId":"change_status_v1_booking_appointments__appointment_id__status_patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"appointment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Appointment Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusChangeIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/booking/professionals/{professional_id}/availability":{"put":{"tags":["booking"],"summary":"Replace a professional's week at one location","operationId":"replace_availability_v1_booking_professionals__professional_id__availability_put","security":[{"BearerAuth":[]}],"parameters":[{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AvailabilityReplaceIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AvailabilityRuleOut"},"title":"Response Replace Availability V1 Booking Professionals  Professional Id  Availability Put"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["booking"],"summary":"A professional's week at one location","operationId":"read_availability_v1_booking_professionals__professional_id__availability_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}},{"name":"branch_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Branch Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/AvailabilityRuleOut"},"title":"Response Read Availability V1 Booking Professionals  Professional Id  Availability Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/booking/professionals/{professional_id}/time-off":{"post":{"tags":["booking"],"summary":"Time off for a professional (whole days) - Scheduling MVP","description":"Adjustment 11: only APPROVED time off removes days from availability. The\nprofessional asks (pending); the shop's schedule.edit approves or writes it\napproved outright.","operationId":"create_time_off_v1_booking_professionals__professional_id__time_off_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeOffIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeOffOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true},"get":{"tags":["booking"],"summary":"A professional's time off, pending and approved","operationId":"list_time_off_v1_booking_professionals__professional_id__time_off_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TimeOffOut"},"title":"Response List Time Off V1 Booking Professionals  Professional Id  Time Off Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/booking/professionals/{professional_id}/time-off/{time_off_id}/approve":{"post":{"tags":["booking"],"summary":"Approve a pending request (schedule.edit)","operationId":"approve_time_off_v1_booking_professionals__professional_id__time_off__time_off_id__approve_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}},{"name":"time_off_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Time Off Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeOffOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/booking/professionals/{professional_id}/time-off/{time_off_id}":{"delete":{"tags":["booking"],"summary":"Withdraw time off","operationId":"delete_time_off_v1_booking_professionals__professional_id__time_off__time_off_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"professional_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Professional Id"}},{"name":"time_off_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Time Off Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/booking/time-blocks":{"post":{"tags":["booking"],"summary":"Block time (a break, a holiday, or the whole shop)","description":"Leave `professional_id` out to close the WHOLE location for that window.\n\nSay when EITHER as instants (`starts_at`/`ends_at`, SCH-06) OR as the branch's own local\ndates (`start_date`/`end_date`, with optional times — his APPOINTMENTS screen 8). The\ndates are read in the LOCATION's clock, never the caller's, and `end_date` is inclusive.","operationId":"create_time_block_v1_booking_time_blocks_post","security":[{"BearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeBlockIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeBlockOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"get":{"tags":["booking"],"summary":"The blocks at a location over a range of its local days","description":"What was blocked, read back. schedule.view_all sees the branch; view_own\nsees the whole-branch closures and their own column only, as on the agenda.","operationId":"list_time_blocks_v1_booking_time_blocks_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"branch_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Branch Id"}},{"name":"date_from","in":"query","required":true,"schema":{"type":"string","format":"date","description":"First local day, in the branch's own timezone","title":"Date From"},"description":"First local day, in the branch's own timezone"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Last local day. Defaults to date_from.","title":"Date To"},"description":"Last local day. Defaults to date_from."},{"name":"professional_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Professional Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/TimeBlockOut"},"title":"Response List Time Blocks V1 Booking Time Blocks Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/booking/time-block-reasons":{"get":{"tags":["booking"],"summary":"The reasons his Block Time screen offers (APPOINTMENTS v1.2 §9)","description":"His controlled enum, answered instead of spelled on a screen.\n\nA reference list and nobody's business data, so any signed-in account may read it — the\napp needs it before it knows which branch the block will be for.","operationId":"time_block_reasons_v1_booking_time_block_reasons_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/TimeBlockReasonOut"},"type":"array","title":"Response Time Block Reasons V1 Booking Time Block Reasons Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/booking/time-blocks/{block_id}":{"patch":{"tags":["booking"],"summary":"Edit a block — his screens 4, 5 and 6 \"Edit Block\"","description":"Only the fields sent change. schedule.edit at the block's location; 404 when it is\nnot this caller's business.","operationId":"update_time_block_v1_booking_time_blocks__block_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"block_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Block Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeBlockPatch"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TimeBlockOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true},"delete":{"tags":["booking"],"summary":"Remove a block — SCH-06 \"Delete This Block\"","description":"schedule.edit at the block's location. 404 when it is not there.","operationId":"delete_time_block_v1_booking_time_blocks__block_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"block_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Block Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/booking/appointments/{appointment_id}/checkout":{"post":{"tags":["booking"],"summary":"Pay for an appointment and confirm it","description":"The client pays. Booking hands money the frozen price and the compensation terms\nin force when the appointment was made; money charges, distributes and returns the\nreceipt. Paying is what confirms the appointment.","operationId":"checkout_v1_booking_appointments__appointment_id__checkout_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"appointment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Appointment Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__booking__schemas__CheckoutIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"object","additionalProperties":true,"title":"Response Checkout V1 Booking Appointments  Appointment Id  Checkout Post"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/branches/{branch_id}/hours":{"get":{"tags":["booking"],"summary":"When this location is open","operationId":"read_branch_hours_v1_businesses__business_id__branches__branch_id__hours_get","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"branch_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Branch Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BranchHoursOut"},"title":"Response Read Branch Hours V1 Businesses  Business Id  Branches  Branch Id  Hours Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"put":{"tags":["booking"],"summary":"Replace this location's opening hours","operationId":"replace_branch_hours_v1_businesses__business_id__branches__branch_id__hours_put","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"branch_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Branch Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchHoursReplaceIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/BranchHoursOut"},"title":"Response Replace Branch Hours V1 Businesses  Business Id  Branches  Branch Id  Hours Put"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/branches/{branch_id}/hour-overrides":{"get":{"tags":["booking"],"summary":"This location's date exceptions in a range - Scheduling MVP","operationId":"list_hour_overrides_v1_businesses__business_id__branches__branch_id__hour_overrides_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"branch_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Branch Id"}},{"name":"date_from","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Date From"}},{"name":"date_to","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Date To"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/HourOverrideOut"},"title":"Response List Hour Overrides V1 Businesses  Business Id  Branches  Branch Id  Hour Overrides Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/branches/{branch_id}/hour-overrides/{on_date}":{"put":{"tags":["booking"],"summary":"Close this location on a date, or open it with other hours - Scheduling MVP","description":"His adjustment 11: a date-specific override is part of the availability\ncalculation. It always was (the engine read this table); now it can be written.","operationId":"set_hour_override_v1_businesses__business_id__branches__branch_id__hour_overrides__on_date__put","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"branch_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Branch Id"}},{"name":"on_date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"On Date"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HourOverrideIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HourOverrideOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["booking"],"summary":"Back to the weekly hours on that date","operationId":"delete_hour_override_v1_businesses__business_id__branches__branch_id__hour_overrides__on_date__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"branch_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Branch Id"}},{"name":"on_date","in":"path","required":true,"schema":{"type":"string","format":"date","title":"On Date"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/appointments":{"post":{"tags":["booking"],"summary":"The shop books somebody in — his decision 12","description":"Walk-ins and bookings taken at the counter or over the phone.\n\n\"Authorised owner, manager or front desk may create appointments for clients\n and register walk-ins. They must identify an existing client or a new/guest\n client, and a payment method. A walk-in must never break the ledger nor\n bypass permissions.\"\n\nIt goes through the ordinary booking path — the same slot validation, the\nsame exclusion constraint, the same race handling — so a walk-in cannot\ndouble-book a chair any more than an app booking can. What differs is only\nwhere the money is: a client with a MyLook account can be booked to pay in\ntheir own app, and anything else is settled at the counter, where MyLook\ntakes nothing and a trigger on `payments` refuses any later claim.","operationId":"create_staff_appointment_v1_businesses__business_id__appointments_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StaffBookingIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AppointmentDetailOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/branches/{branch_id}/agenda":{"get":{"tags":["booking"],"summary":"Who is coming in — the business-side calendar","description":"What a professional, a front desk or an owner sees.\n\nA professional holds only schedule.view_own, so they get their own column and\nnever a colleague's. Money is stripped per row for chair-rent professionals:\ntheir takings are theirs, and the owner sees the rent instead.","operationId":"branch_agenda_v1_businesses__business_id__branches__branch_id__agenda_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"branch_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Branch Id"}},{"name":"date_from","in":"query","required":true,"schema":{"type":"string","format":"date","description":"First local day, in the branch's own timezone","title":"Date From"},"description":"First local day, in the branch's own timezone"},{"name":"date_to","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Last local day. Defaults to date_from.","title":"Date To"},"description":"Last local day. Defaults to date_from."},{"name":"professional_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Professional Id"}},{"name":"include_cancelled","in":"query","required":false,"schema":{"type":"boolean","default":false,"title":"Include Cancelled"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgendaOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/team-pulse":{"get":{"tags":["booking"],"summary":"His decision 26 — the five Team numbers","description":"Computed from real Schedule and Team rows, or refused with a reason.\n\nAnyone who can see the team can read them — they describe the team, and the\nsame gate governs the roster they sit above.","operationId":"team_pulse_v1_businesses__business_id__team_pulse_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"branch_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TeamPulseOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/professional/day":{"get":{"tags":["booking"],"summary":"My own day - agenda, blocks and open time (his APPOINTMENTS v1.2)","description":"WHAT I HAVE TODAY, in one read.\n\nHis §2 puts the day summary, the agenda and the open time on one screen, and his §50 asks that\na secondary failure not take the screen down - so they come back together rather than as four\nrequests that can half-succeed.\n\nThe scope is the signed-in professional: their own bookings, their own blocks, their own hours.\nA colleague's row cannot appear because the query never leaves the caller's own professional\nids (his §51).","operationId":"my_day_read_v1_me_professional_day_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"date","in":"query","required":true,"schema":{"type":"string","format":"date","title":"Date"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProfessionalDayOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/professional/appointments":{"post":{"tags":["booking"],"summary":"Book somebody into one of my own open gaps (his §14)","description":"HIS §14, from the gap his §13 offered.\n\n\"Muy importante: volver a validar disponibilidad en backend antes de guardar. Porque otro\nbooking pudo entrar mientras el profesional estaba llenando la pantalla.\" That revalidation\nis the ordinary booking path's, not a second copy of it: this route takes the professional\nidentity from the caller and hands the rest to the same function the shop's own counter uses.\n\nThe answer is the row his day draws, so the screen can show what it just created without a\nsecond read.","operationId":"book_into_my_gap_v1_me_professional_appointments_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MyBookingIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/DayBookingOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/me/professional/needs-attention":{"get":{"tags":["booking"],"summary":"What is waiting on me today (his §26 aggregator)","description":"HIS §26: \"un aggregator, no un nuevo dominio.\"\n\nCounted, every time, from the bookings and blocks that already exist. There is no table\nbehind this and no counter anybody has to remember to update, which is the only way a list\nof things needing attention stays true.","operationId":"my_needs_attention_v1_me_professional_needs_attention_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"date","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"The local day to look at. Left out, it is TODAY in the shop's own clock - which is the only clock that can answer it for somebody travelling.","title":"Date"},"description":"The local day to look at. Left out, it is TODAY in the shop's own clock - which is the only clock that can answer it for somebody travelling."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NeedsAttentionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/professional/services":{"get":{"tags":["booking"],"summary":"What I can book at a location (his §14 service picker)","description":"HIS §14's service picker, already intersected with the skill that makes a slot real.\n\nA form built from the shop's whole menu would offer services the create refuses, and the\nperson would find out after filling the screen in.","operationId":"my_bookable_services_v1_me_professional_services_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"branch_id","in":"query","required":true,"schema":{"type":"string","format":"uuid","title":"Branch Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SellableServiceOut"},"title":"Response My Bookable Services V1 Me Professional Services Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/professional/back-at":{"get":{"tags":["booking"],"summary":"When I am back after a day off (his §11, derived)","description":"HIS SCREEN 8 prints this while the block is still being typed, so it cannot come from a\nblock that does not exist yet — and §11 forbids keeping a second calendar for it. It is\nderived from the base schedule, by the same function his day-off card uses.","operationId":"my_back_at_v1_me_professional_back_at_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"after","in":"query","required":true,"schema":{"type":"string","format":"date","description":"The last day away, in the shop's own clock","title":"After"},"description":"The last day away, in the shop's own clock"}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/BackAtOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/professional/today":{"get":{"tags":["booking"],"summary":"HIS TODAY / HOY v1.0 - the professional's daily centre","description":"HIS TWELVE BLOCKS, in one call.\n\n\"Today NO es dueno de los datos. Today es una read-model / aggregation surface\" (his §32), so\nevery number here belongs to another domain and this route owns none of them.\n\nONE CALL, NOT TWELVE, because his §36 asks for the P0 blocks together and his §42's pull to\nrefresh is one gesture. His §39's error boundaries survive it: a block that could not be read\nnames itself in `unavailable` and the rest of the screen is drawn.","operationId":"my_today_v1_me_professional_today_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"on","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"description":"Which day, in the shop's own clock. Omitted means today THERE, which is the only clock his screen may use.","title":"On"},"description":"Which day, in the shop's own clock. Omitted means today THERE, which is the only clock his screen may use."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TodayOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/me/professional/next-service":{"get":{"tags":["booking"],"summary":"My next appointment - today, tomorrow or next week (his TODAY v1.0 §7)","description":"THE EARLIEST FUTURE ACTIVE BOOKING. His §7 writes the query and its own warning: \"Nunca\nlimitarlo solo a hoy.\" No booking answers `appointment: null`, which is his empty state and\nnot an error.","operationId":"my_next_service_v1_me_professional_next_service_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NextServiceOut"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/media":{"post":{"tags":["media"],"summary":"Upload an image and get the key to store on an entity","operationId":"upload_v1_media_post","requestBody":{"content":{"multipart/form-data":{"schema":{"$ref":"#/components/schemas/Body_upload_v1_media_post"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MediaOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/media/{key}":{"get":{"tags":["media"],"summary":"Serve an image (local storage only)","operationId":"serve_v1_media__key__get","security":[{"BearerAuth":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}},{"name":"exp","in":"query","required":false,"schema":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Exp"}},{"name":"sig","in":"query","required":false,"schema":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sig"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true},"delete":{"tags":["media"],"summary":"Remove an image","operationId":"remove_v1_media__key__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"key","in":"path","required":true,"schema":{"type":"string","title":"Key"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"x-conceal-resource-existence":true}},"/v1/businesses/{business_id}/media":{"get":{"tags":["media"],"summary":"Images belonging to a business","operationId":"business_media_v1_businesses__business_id__media_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/MediaOut"},"title":"Response Business Media V1 Businesses  Business Id  Media Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/promotions":{"get":{"tags":["promotions"],"summary":"Special Offers & Promotions — the Discover rail","description":"Public. Live offers only — switched on, started, and not yet ended — from\nbusinesses that are 'active'. A chain-wide offer appears ONCE, at its nearest\nlocation, so one shop cannot fill the rail with the same card.","operationId":"list_promotions_v1_promotions_get","parameters":[{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":90,"minimum":-90},{"type":"null"}],"description":"Where the person is. Omitted = no distance, no distance sort.","title":"Lat"},"description":"Where the person is. Omitted = no distance, no distance sort."},{"name":"lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":180,"minimum":-180},{"type":"null"}],"title":"Lng"}},{"name":"radius_miles","in":"query","required":false,"schema":{"type":"number","maximum":200,"exclusiveMinimum":0,"default":10.0,"title":"Radius Miles"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"description":"Category slug, e.g. hair-salon","title":"Category"},"description":"Category slug, e.g. hair-salon"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":20,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PromotionCardOut"},"title":"Response List Promotions V1 Promotions Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/promotions/{promotion_id}":{"get":{"tags":["promotions"],"summary":"One offer","description":"Public — tapping a card has to lead somewhere. An offer belonging to a\nbusiness that is not 'active' answers exactly as a missing one does.","operationId":"read_promotion_v1_promotions__promotion_id__get","parameters":[{"name":"promotion_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Promotion Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/promotions/{promotion_id}/quote":{"post":{"tags":["promotions"],"summary":"What this offer does to this booking","description":"The question the booking flow asks before anything is charged.\n\nThe body names the service and the location. It does NOT carry a price or a\ndiscount, and there is no field in which it could: the price is read from the\ncatalog, the discount is computed from the offer, and entitlement is checked\nagainst the offer's own rules. Every figure returned comes from\nmoney.build_quote, the one function allowed to decide what somebody pays.","operationId":"quote_promotion_v1_promotions__promotion_id__quote_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"promotion_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Promotion Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotionQuoteIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotionQuoteOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/discovery/transparency":{"get":{"tags":["intelligence"],"summary":"What MyLook may use to recommend, and how to switch it off","description":"Public — HIS REFINEMENT 07 (2026-09-08).\n\nA person is entitled to know what MAY be used about them, what may NEVER be,\nthat every recommendation carries a reason, and how to turn personalization\noff. They are not entitled to the ranking's internals, and publishing those\nwould be handing anybody who wants to game the rail a specification.\n\nSo this is the smaller, public half. The whole contract — the pipeline, the\nsignals actually read, the provider behaviour — is `/contract` below, which\nis platform staff only and is what the certification suite asserts against.","operationId":"recommendation_transparency_v1_discovery_transparency_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Recommendation Transparency V1 Discovery Transparency Get"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/discovery/contract":{"get":{"tags":["intelligence"],"summary":"DOM-08 For You — the full internal contract (a capability, not a title)","description":"REQUIRES `intelligence.contract.read` — HIS REFINEMENT 04.\n\nIt used to accept any `admin` OR `moderator`, and he was right that a job\ntitle is the wrong question: \"no dar acceso por un título genérico si no\nexiste necesidad operacional\". Moderating content has never needed the\nranking's internals. `admin` holds the capability by default; anybody else\nholds it because somebody granted it to them on purpose, and it can be\nwithdrawn without editing code.\n\nHis refinement 07 drew the line between this and the public half.\n\nHis decision 147 approved the ARCHITECTURE and kept the surface hidden, and\nthe rules a recommender obeys are worth nothing if they live only in a\ndocument. This is that document as an answerable object: the pipeline, what\nmay be ranked on, what may never be, what the engine actually reads today,\nthe opt-out and what happens when the provider fails.\n\n`verify_for_you_contract` asserts the running engine against it, which is\nthe whole reason it exists in this form rather than in a slide.","operationId":"for_you_contract_v1_discovery_contract_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response For You Contract V1 Discovery Contract Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/discovery/recommendations":{"get":{"tags":["intelligence"],"summary":"Personalized picks for the signed-in person - his decision 20","description":"Built from what this person saved and booked, chosen only among shops that\nare actually near and public, each with the reason. `insufficient_history`\nand an empty list when there is nothing to reason from - never padded.","operationId":"recommendations_v1_discovery_recommendations_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"lat","in":"query","required":true,"schema":{"type":"number","maximum":90,"minimum":-90,"title":"Lat"}},{"name":"lng","in":"query","required":true,"schema":{"type":"number","maximum":180,"minimum":-180,"title":"Lng"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RecommendationsOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/promotions":{"get":{"tags":["promotions"],"summary":"A shop's offers","description":"Public: what this shop is running right now. Offers that have ended, or that\nwere switched off, are not somebody else's business — the shop's own view of\nthose is /promotions/manage.","operationId":"business_promotions_v1_businesses__business_id__promotions_get","parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PromotionOut"},"title":"Response Business Promotions V1 Businesses  Business Id  Promotions Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"post":{"tags":["promotions"],"summary":"Publish an offer","operationId":"create_promotion_v1_businesses__business_id__promotions_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotionCreateIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/promotions/manage":{"get":{"tags":["promotions"],"summary":"Every offer, including ended and switched off","description":"The shop's own list. Without it, deactivating an offer would hide it from the\nonly people who might want it back.","operationId":"manage_promotions_v1_businesses__business_id__promotions_manage_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/PromotionOut"},"title":"Response Manage Promotions V1 Businesses  Business Id  Promotions Manage Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/promotions/{promotion_id}":{"patch":{"tags":["promotions"],"summary":"Edit an offer, or switch it back on","operationId":"update_promotion_v1_businesses__business_id__promotions__promotion_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"promotion_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Promotion Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotionUpdateIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["promotions"],"summary":"Stop an offer — switched off, not destroyed","description":"Returns the offer with is_active false rather than a bare 204, because a\nreceipt that says \"20% OFF\" has to keep meaning something: the row survives, the\nredemptions still point at it, and a PATCH can put it back on the rail.","operationId":"deactivate_promotion_v1_businesses__business_id__promotions__promotion_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"promotion_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Promotion Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PromotionOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/products/top-selling":{"get":{"tags":["shop"],"summary":"Discover's Shop rail — Top Selling Beauty Products, with its rule","description":"Public. HIS DECISION 144 (2026-09-08), APPROVED — the rail says \"Top\nSelling\" and this is what that means, published with every answer: a ROLLING\n30-day window, net of returns, ranked by units and not by money.\n\nUntil this decision the rail called the ordinary shelf search, which sorts by\nDISTANCE as soon as a position is sent — and Discover always sends one. A\nrail titled Top Selling was showing the nearest products to everybody who\never opened it. `discovery.top_selling` is now its own query with his own\norder, and the four tie-break levels travel in `tie_break` so a shop can see\nwhy it placed where it did.\n\nHis six scopes are the query parameters: global, region, city, near me,\ncategory and business. They compose.","operationId":"top_selling_v1_products_top_selling_get","parameters":[{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":90,"minimum":-90},{"type":"null"}],"title":"Lat"}},{"name":"lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":180,"minimum":-180},{"type":"null"}],"title":"Lng"}},{"name":"radius_miles","in":"query","required":false,"schema":{"type":"number","maximum":200,"exclusiveMinimum":0,"default":10.0,"title":"Radius Miles"}},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"title":"Category"}},{"name":"city","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"description":"His CITY scope — 'top selling in Miami'.","title":"City"},"description":"His CITY scope — 'top selling in Miami'."},{"name":"state","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"description":"His REGION scope — two-letter state, e.g. FL.","title":"State"},"description":"His REGION scope — two-letter state, e.g. FL."},{"name":"business_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"His BUSINESS scope — one shop's own best sellers.","title":"Business Id"},"description":"His BUSINESS scope — one shop's own best sellers."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":10,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/TopSellingOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/products":{"get":{"tags":["shop"],"summary":"Shop — top beauty products near you","description":"Public: no sign-in needed.\n\nCross-business, unlike `/businesses/{id}/products`: one row per product, at\nthe nearest branch that sells it, with the shop attached. The price is the\nshop's own — the branch's override where it has set one.","operationId":"search_products_v1_products_get","parameters":[{"name":"lat","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":90,"minimum":-90},{"type":"null"}],"description":"Where the person is. Omitted = no distance, no distance sort.","title":"Lat"},"description":"Where the person is. Omitted = no distance, no distance sort."},{"name":"lng","in":"query","required":false,"schema":{"anyOf":[{"type":"number","maximum":180,"minimum":-180},{"type":"null"}],"title":"Lng"}},{"name":"radius_miles","in":"query","required":false,"schema":{"type":"number","maximum":200,"exclusiveMinimum":0,"default":10.0,"title":"Radius Miles"}},{"name":"q","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"description":"Name, brand or description","title":"Q"},"description":"Name, brand or description"},{"name":"category","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"description":"Category slug, e.g. hair-salon","title":"Category"},"description":"Category slug, e.g. hair-salon"},{"name":"in_stock_only","in":"query","required":false,"schema":{"type":"boolean","description":"Only what a shop says it has. Off by default: most shops track no stock, and that is not 'sold out'.","default":false,"title":"In Stock Only"},"description":"Only what a shop says it has. Off by default: most shops track no stock, and that is not 'sold out'."},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"default":25,"title":"Limit"}},{"name":"offset","in":"query","required":false,"schema":{"type":"integer","minimum":0,"default":0,"title":"Offset"}},{"name":"business_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"description":"Only this shop's products — its own Shop tab. The radius is still honoured when a location is sent.","title":"Business Id"},"description":"Only this shop's products — its own Shop tab. The radius is still honoured when a location is sent."}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ProductCardOut"},"title":"Response Search Products V1 Products Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/products/{product_id}":{"get":{"tags":["shop"],"summary":"One product, as its shelf card — his decision 44's favourite needs it","description":"Public. A favourite holds a product's id and nothing else; this reads the\ncard back under the same conditions as the shelf (active product, active\nbusiness and branch, tracked where somebody counts). 404 otherwise.","operationId":"read_product_v1_products__product_id__get","parameters":[{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductCardOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/products/{product_id}/notify-me":{"post":{"tags":["shop"],"summary":"Tell me when this is back in stock (his decision 43)","description":"Refused with `already_in_stock` while it can be bought — a notice for\nsomething already there would never fire, and the person would wait for it.\nAsking twice is one ask. It does NOT hold a unit: Reserve and Notify Me are\ndifferent things in his sentence, and a notice that also held stock would be\na reservation by another name.","operationId":"notify_me_v1_products__product_id__notify_me_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotifyMeIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotifyMeOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["shop"],"summary":"Never mind","operationId":"forget_me_v1_products__product_id__notify_me_delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"product_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Product Id"}},{"name":"variant_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Variant Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/products/notify-me/mine":{"get":{"tags":["shop"],"summary":"What I am waiting to hear about","operationId":"my_notify_requests_v1_products_notify_me_mine_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/NotifyMeOut"},"type":"array","title":"Response My Notify Requests V1 Products Notify Me Mine Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/cart":{"get":{"tags":["shop"],"summary":"My baskets","description":"One per shop being bought from. An order is fulfilled by one shop and paid\nto one shop, so a basket spanning three of them cannot become one order.","operationId":"my_carts_v1_cart_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"items":{"$ref":"#/components/schemas/CartOut"},"type":"array","title":"Response My Carts V1 Cart Get"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/cart/items":{"post":{"tags":["shop"],"summary":"Add to Cart","description":"Tapping it twice raises the quantity rather than making a second line.\n\nNothing about price is read from the body — the total that comes back was\ncomputed here from the shop's own catalogue.","operationId":"add_item_v1_cart_items_post","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartItemIn"}}},"required":true},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"security":[{"BearerAuth":[]}]}},"/v1/cart/items/{item_id}":{"patch":{"tags":["shop"],"summary":"Change how many","operationId":"set_quantity_v1_cart_items__item_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"item_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Item Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartQuantityIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["shop"],"summary":"Take it out","operationId":"remove_item_v1_cart_items__item_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"item_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Item Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/cart/{cart_id}":{"get":{"tags":["shop"],"summary":"One basket","description":"Somebody else's is a 404, not a 403: a refusal would confirm it exists.","operationId":"read_cart_v1_cart__cart_id__get","security":[{"BearerAuth":[]}],"parameters":[{"name":"cart_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cart Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CartOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["shop"],"summary":"Abandon a basket","operationId":"abandon_cart_v1_cart__cart_id__delete","security":[{"BearerAuth":[]}],"parameters":[{"name":"cart_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cart Id"}}],"responses":{"204":{"description":"Successful Response"},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/cart/{cart_id}/checkout":{"post":{"tags":["shop"],"summary":"Buy what is in it","description":"The cart is re-priced from the shop's catalogue and charged through money,\nin one transaction. A second attempt on the same cart is refused, not charged\nagain.","operationId":"checkout_v1_cart__cart_id__checkout_post","security":[{"BearerAuth":[]}],"parameters":[{"name":"cart_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Cart Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/malu__domains__commerce__schemas__CheckoutIn"}}}},"responses":{"201":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/orders/mine":{"get":{"tags":["shop"],"summary":"What I bought","operationId":"my_orders_v1_orders_mine_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/OrderOut"},"title":"Response My Orders V1 Orders Mine Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/orders/{order_id}":{"get":{"tags":["shop"],"summary":"One order, as its buyer","description":"Only the person who bought it. Anyone else gets a 404 — including the shop,\nwhich reads its own sales through /businesses/{id}/orders.","operationId":"read_order_v1_orders__order_id__get","security":[{"BearerAuth":[]}],"parameters":[{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Order Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/orders":{"get":{"tags":["shop"],"summary":"What the shop sold","description":"An order shows what the customer paid, so this is a finance capability:\nowner and manager, never a professional. A branch-scoped manager sees their\nown location only.","operationId":"shop_orders_v1_businesses__business_id__orders_get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"branch_id","in":"query","required":false,"schema":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"}},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Status"}},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":200,"minimum":1,"default":50,"title":"Limit"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/ShopOrderOut"},"title":"Response Shop Orders V1 Businesses  Business Id  Orders Get"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/orders/{order_id}":{"get":{"tags":["shop"],"summary":"One order, as the shop","operationId":"shop_order_v1_businesses__business_id__orders__order_id__get","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Order Id"}}],"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShopOrderOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["shop"],"summary":"Accepted, preparing, ready, handed over, or cancelled","description":"His decision 46's flow: Paid → Accepted → Preparing → Ready for Pickup →\nCompleted. Forward only, and a shop may skip ahead. The buyer is notified\nwhen it becomes Ready, and at no other step.\n\nCANCELLING A PAID ORDER REFUNDS IT — his decision 4: \"Not yet ready for\npickup: the seller may cancel and MUST refund.\" The order comes to rest as\n`refunded` rather than `cancelled`, because money moved and the row has to\nkeep saying so. Every component the buyer paid comes back, MyLook's 5%\ncommission reverses proportionally, the goods go back on the shelf and the\nbuyer is told. Once the shop has announced the order as READY, or it has\nbeen collected, no rule of his covers it and cancelling is still refused.","operationId":"advance_order_v1_businesses__business_id__orders__order_id__patch","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Order Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderStatusIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShopOrderOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/v1/businesses/{business_id}/orders/{order_id}/pickup-window":{"put":{"tags":["shop"],"summary":"When the shop thinks it can be collected","description":"The shop's own estimate, and never the platform's — his decision 47 is\nthat there is no automatic exact hour. Send both instants to give or change\nthe estimate, neither to clear it. One alone is refused.","operationId":"set_pickup_window_v1_businesses__business_id__orders__order_id__pickup_window_put","security":[{"BearerAuth":[]}],"parameters":[{"name":"business_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Business Id"}},{"name":"order_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","title":"Order Id"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PickupWindowIn"}}}},"responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ShopOrderOut"}}}},"422":{"description":"The request body or query is malformed — a missing field, a wrong type, a value out of range.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Not signed in, or the access token has expired or been revoked. Refresh at POST /v1/auth/refresh, or sign in again.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Signed in, but not allowed to do this — the wrong role, or the right role at a different business or branch.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such thing. Also returned when it exists and this caller may not see it: the two are deliberately indistinguishable, so a 404 cannot be used to discover what exists.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/":{"get":{"tags":["system"],"summary":"What this is, and where to go next","description":"Anyone opening the bare address deserves better than {\"detail\":\"Not Found\"}.\n\nThat is a technically correct 404 and a useless one: it reads as a broken\nserver when the server is working perfectly, and it tells whoever is reviewing\nthe deployment nothing about where to look.","operationId":"root__get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Root  Get"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/health":{"get":{"tags":["system"],"summary":"Liveness, database check, and process identity","operationId":"health_health_get","responses":{"200":{"description":"Successful Response","content":{"application/json":{"schema":{"additionalProperties":true,"type":"object","title":"Response Health Health Get"}}}},"500":{"description":"Something failed unexpectedly. Same envelope, and `detail` is omitted — quote `request_id` when reporting it.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"components":{"schemas":{"AcceptLiabilityIn":{"properties":{"reason":{"type":"string","maxLength":2000,"minLength":3,"title":"Reason"}},"type":"object","required":["reason"],"title":"AcceptLiabilityIn","description":"MyLook accepting fault. His third case, and the only one a person performs.\n\n`reason` is REQUIRED and is stored verbatim. The platform being at fault is a\njudgement about an incident, and a judgement with no stated reason cannot be\ntold apart from a mistake — 036 refuses such a row at the database too."},"AcceptedOut":{"properties":{"status":{"type":"string","title":"Status","default":"accepted"},"detail":{"type":"string","title":"Detail"}},"type":"object","required":["detail"],"title":"AcceptedOut","description":"Deliberately says nothing about whether the address exists."},"AccessMembershipOut":{"properties":{"member_id":{"type":"string","format":"uuid","title":"Member Id"},"role":{"type":"string","title":"Role"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"state":{"type":"string","title":"State"},"capabilities":{"items":{"type":"string"},"type":"array","title":"Capabilities"}},"type":"object","required":["member_id","role","branch_id","state","capabilities"],"title":"AccessMembershipOut","description":"One of the caller's memberships in this business — his decision of 2026-09-14 (CR-SEC-2026-09-14-08): \"Each\nmembership represents: role + scope + state + capabilities.\" `branch_id` null is the whole business; `state` is\nactive or suspended; `capabilities` are this membership's own, and apply only where it does."},"AccountDeletionIn":{"properties":{"confirmation":{"type":"string","maxLength":32,"minLength":1,"title":"Confirmation"}},"type":"object","required":["confirmation"],"title":"AccountDeletionIn","description":"His step 2 — \"Verify & Delete\": the person types DELETE. The platform\nchecks the word, not the app: the interface is never the authority\n(STD-002 page 7, authorization philosophy)."},"AccountDeletionOut":{"properties":{"request_id":{"type":"string","format":"uuid","title":"Request Id"},"deleted":{"additionalProperties":{"type":"integer"},"type":"object","title":"Deleted"},"kept":{"items":{"type":"string"},"type":"array","title":"Kept"},"completed_at":{"type":"string","format":"date-time","title":"Completed At"}},"type":"object","required":["request_id","deleted","kept","completed_at"],"title":"AccountDeletionOut","description":"What happened, in the order of his \"What will be deleted\" list, and what\nSTD-002 page 7 §32 made the platform keep — restricted and anonymised."},"AgendaEntryOut":{"properties":{"appointment_id":{"type":"string","format":"uuid","title":"Appointment Id"},"reference":{"type":"string","title":"Reference"},"starts_at":{"type":"string","format":"date-time","title":"Starts At"},"ends_at":{"type":"string","format":"date-time","title":"Ends At"},"status":{"type":"string","title":"Status"},"professional_id":{"type":"string","format":"uuid","title":"Professional Id"},"professional_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Professional Name"},"client_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Name"},"booked_for_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Booked For Name"},"service_name":{"type":"string","title":"Service Name"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"price_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price Cents"},"client_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Note"}},"type":"object","required":["appointment_id","reference","starts_at","ends_at","status","professional_id","professional_name","client_name","booked_for_name","service_name","duration_minutes","price_cents","client_note"],"title":"AgendaEntryOut","description":"One row on a business-side calendar.\n\nprice_cents is null when the viewer may not see this professional's money —\na chair-rent professional's takings are theirs, and the owner sees the rent\ninstead. Null is not \"free\": it means \"not yours to see\"."},"AgendaOut":{"properties":{"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"timezone":{"type":"string","title":"Timezone"},"date_from":{"type":"string","format":"date","title":"Date From"},"date_to":{"type":"string","format":"date","title":"Date To"},"entries":{"items":{"$ref":"#/components/schemas/AgendaEntryOut"},"type":"array","title":"Entries"}},"type":"object","required":["branch_id","timezone","date_from","date_to","entries"],"title":"AgendaOut","description":"The window that was actually read, so the app never has to guess the\ntimezone the times should be drawn in."},"AgentOut":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id"},"full_name":{"type":"string","title":"Full Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"role":{"type":"string","title":"Role"},"skills":{"items":{"type":"string"},"type":"array","title":"Skills"},"active_cases":{"type":"integer","title":"Active Cases"}},"type":"object","required":["user_id","full_name","role","skills","active_cases"],"title":"AgentOut"},"AgreementCreateIn":{"properties":{"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"model":{"type":"string","pattern":"^(independent|salon_percent|chair_rent)$","title":"Model"},"professional_share_bps":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":0.0},{"type":"null"}],"title":"Professional Share Bps"},"owner_share_bps":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":0.0},{"type":"null"}],"title":"Owner Share Bps"},"rent_amount_cents":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Rent Amount Cents"},"rent_period":{"anyOf":[{"type":"string","pattern":"^(weekly|biweekly|monthly)$"},{"type":"null"}],"title":"Rent Period"},"rent_retention_bps":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":0.0},{"type":"null"}],"title":"Rent Retention Bps"},"rent_cycle_weekday":{"anyOf":[{"type":"integer","maximum":6.0,"minimum":0.0},{"type":"null"}],"title":"Rent Cycle Weekday"},"effective_from":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Effective From"}},"type":"object","required":["branch_id","model"],"title":"AgreementCreateIn","description":"One shape per model, checked before the database sees it:\n\n  independent   — no shares, no rent terms\n  salon_percent — both shares, adding up to 10000 bps (100%)\n  chair_rent    — amount, period and the share withheld from each charge\n\nEverything is basis points and cents: 10000 bps = 100%, 30000 cents = US$300."},"AgreementOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"professional_id":{"type":"string","format":"uuid","title":"Professional Id"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"model":{"type":"string","title":"Model"},"version":{"type":"integer","title":"Version"},"professional_share_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Professional Share Bps"},"owner_share_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Owner Share Bps"},"rent_amount_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rent Amount Cents"},"rent_period":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Rent Period"},"rent_retention_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rent Retention Bps"},"rent_cycle_weekday":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rent Cycle Weekday"},"status":{"type":"string","title":"Status"},"effective_from":{"type":"string","format":"date","title":"Effective From"},"effective_to":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Effective To"},"approved_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Approved By"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","professional_id","branch_id","model","version","professional_share_bps","owner_share_bps","rent_amount_cents","rent_period","rent_retention_bps","rent_cycle_weekday","status","effective_from","effective_to","approved_by","created_at"],"title":"AgreementOut"},"AppointmentCreateIn":{"properties":{"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"professional_id":{"type":"string","format":"uuid","title":"Professional Id"},"service_id":{"type":"string","format":"uuid","title":"Service Id"},"starts_at":{"type":"string","format":"date-time","title":"Starts At"},"client_note":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Client Note"},"booked_for_name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Booked For Name"},"reference_image_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reference Image Key"}},"type":"object","required":["branch_id","professional_id","service_id","starts_at"],"title":"AppointmentCreateIn"},"AppointmentDetailOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"reference":{"type":"string","title":"Reference"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"professional_id":{"type":"string","format":"uuid","title":"Professional Id"},"client_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Client User Id"},"service_id":{"type":"string","format":"uuid","title":"Service Id"},"agreement_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Agreement Id"},"starts_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Starts At"},"ends_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ends At"},"guest_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Guest Phone"},"payment_channel":{"type":"string","title":"Payment Channel","default":"mylook"},"created_by_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By User Id"},"service_name_snapshot":{"type":"string","title":"Service Name Snapshot"},"duration_minutes_snapshot":{"type":"integer","title":"Duration Minutes Snapshot"},"price_cents_snapshot":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price Cents Snapshot"},"options_snapshot":{"items":{},"type":"array","title":"Options Snapshot"},"status":{"type":"string","enum":["pending_payment","confirmed","checked_in","in_progress","completed","cancelled_client","cancelled_business","no_show"],"title":"Status"},"client_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Note"},"reference_image_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reference Image Key"},"booked_for_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Booked For Name"},"source":{"type":"string","title":"Source"},"cancelled_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancelled At"},"cancellation_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancellation Reason"},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completed At"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"pending_move":{"anyOf":[{"$ref":"#/components/schemas/MoveProposalOut"},{"type":"null"}]},"events":{"items":{"$ref":"#/components/schemas/AppointmentEventOut"},"type":"array","title":"Events","default":[]},"internal_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Internal Note"},"internal_note_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Internal Note At"},"internal_note_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Internal Note By"},"client_since":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Client Since"},"payment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Payment Id"},"paid_total_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Paid Total Cents"},"refunded_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Refunded Cents"},"card_brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Card Brand"},"card_last4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Card Last4"},"paid_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Paid At"}},"type":"object","required":["id","reference","branch_id","professional_id","service_id","agreement_id","starts_at","ends_at","service_name_snapshot","duration_minutes_snapshot","price_cents_snapshot","options_snapshot","status","client_note","reference_image_key","booked_for_name","source","cancelled_at","cancellation_reason","completed_at","created_at"],"title":"AppointmentDetailOut","description":"With its timeline — the audit trail is part of the appointment, not a footnote."},"AppointmentEventOut":{"properties":{"from_status":{"anyOf":[{"type":"string","enum":["pending_payment","confirmed","checked_in","in_progress","completed","cancelled_client","cancelled_business","no_show"]},{"type":"null"}],"title":"From Status"},"to_status":{"type":"string","enum":["pending_payment","confirmed","checked_in","in_progress","completed","cancelled_client","cancelled_business","no_show"],"title":"To Status"},"actor_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Actor Id"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["from_status","to_status","actor_id","note","created_at"],"title":"AppointmentEventOut"},"ApprovalOut":{"properties":{"kind":{"type":"string","title":"Kind"},"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"subtitle":{"type":"string","title":"Subtitle"},"since":{"type":"string","format":"date-time","title":"Since"},"href":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Href"}},"type":"object","required":["kind","id","name","subtitle","since","href"],"title":"ApprovalOut"},"ArticleDetailOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"title":{"type":"string","title":"Title"},"domain":{"type":"string","title":"Domain"},"domain_label":{"type":"string","title":"Domain Label"},"language":{"type":"string","title":"Language"},"status":{"type":"string","title":"Status"},"version":{"type":"string","title":"Version"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"author":{"anyOf":[{"$ref":"#/components/schemas/malu__domains__knowledge__schemas__PersonOut"},{"type":"null"}]},"owner":{"anyOf":[{"$ref":"#/components/schemas/malu__domains__knowledge__schemas__PersonOut"},{"type":"null"}]},"block_count":{"type":"integer","title":"Block Count"},"blocks_review_needed":{"type":"integer","title":"Blocks Review Needed"},"attention":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attention"},"views_count":{"type":"integer","title":"Views Count"},"review_requested_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Review Requested At"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"},"first_published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"First Published At"},"outdated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Outdated At"},"outdated_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outdated Reason"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Archived At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"blocks":{"items":{"$ref":"#/components/schemas/BlockOut"},"type":"array","title":"Blocks"},"events":{"items":{"$ref":"#/components/schemas/malu__domains__knowledge__schemas__EventOut"},"type":"array","title":"Events"}},"type":"object","required":["id","code","title","domain","domain_label","language","status","version","summary","tags","author","owner","block_count","blocks_review_needed","attention","views_count","review_requested_at","published_at","first_published_at","outdated_at","outdated_reason","archived_at","created_at","updated_at","blocks","events"],"title":"ArticleDetailOut"},"ArticleIn":{"properties":{"title":{"type":"string","maxLength":200,"minLength":3,"title":"Title"},"domain":{"type":"string","enum":["customer_help","professional_help","support_procedures","trust_safety","policies"],"title":"Domain"},"language":{"type":"string","maxLength":10,"minLength":2,"title":"Language","default":"en"},"code":{"anyOf":[{"type":"string","maxLength":40,"minLength":2},{"type":"null"}],"title":"Code"},"summary":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Summary"},"tags":{"items":{"type":"string"},"type":"array","maxItems":20,"title":"Tags"},"blocks":{"items":{"$ref":"#/components/schemas/BlockIn"},"type":"array","maxItems":60,"title":"Blocks"}},"type":"object","required":["title","domain"],"title":"ArticleIn"},"ArticleOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"title":{"type":"string","title":"Title"},"domain":{"type":"string","title":"Domain"},"domain_label":{"type":"string","title":"Domain Label"},"language":{"type":"string","title":"Language"},"status":{"type":"string","title":"Status"},"version":{"type":"string","title":"Version"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"author":{"anyOf":[{"$ref":"#/components/schemas/malu__domains__knowledge__schemas__PersonOut"},{"type":"null"}]},"owner":{"anyOf":[{"$ref":"#/components/schemas/malu__domains__knowledge__schemas__PersonOut"},{"type":"null"}]},"block_count":{"type":"integer","title":"Block Count"},"blocks_review_needed":{"type":"integer","title":"Blocks Review Needed"},"attention":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attention"},"views_count":{"type":"integer","title":"Views Count"},"review_requested_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Review Requested At"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"},"first_published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"First Published At"},"outdated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Outdated At"},"outdated_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Outdated Reason"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Archived At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","code","title","domain","domain_label","language","status","version","summary","tags","author","owner","block_count","blocks_review_needed","attention","views_count","review_requested_at","published_at","first_published_at","outdated_at","outdated_reason","archived_at","created_at","updated_at"],"title":"ArticleOut"},"ArticleUpdateIn":{"properties":{"title":{"anyOf":[{"type":"string","maxLength":200,"minLength":3},{"type":"null"}],"title":"Title"},"domain":{"anyOf":[{"type":"string","enum":["customer_help","professional_help","support_procedures","trust_safety","policies"]},{"type":"null"}],"title":"Domain"},"language":{"anyOf":[{"type":"string","maxLength":10,"minLength":2},{"type":"null"}],"title":"Language"},"code":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Code"},"summary":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Summary"},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":20},{"type":"null"}],"title":"Tags"},"owner_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Owner Id"},"blocks":{"anyOf":[{"items":{"$ref":"#/components/schemas/BlockIn"},"type":"array","maxItems":60},{"type":"null"}],"title":"Blocks"}},"type":"object","title":"ArticleUpdateIn","description":"Omitted fields are left alone; `blocks`, when sent, replaces the whole list\nin the order given (his blocks are dragged into order)."},"AssignedCaseOut":{"properties":{"id":{"type":"string","title":"Id"},"case_number":{"type":"string","title":"Case Number"},"subject":{"type":"string","title":"Subject"},"category":{"type":"string","title":"Category"},"status":{"type":"string","title":"Status"},"priority":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Priority"},"sla_due_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sla Due At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","case_number","subject","category","status","priority","sla_due_at","created_at"],"title":"AssignedCaseOut"},"AssigneeOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"}},"type":"object","required":["id","name"],"title":"AssigneeOut"},"AttentionItemOut":{"properties":{"kind":{"type":"string","title":"Kind"},"count":{"type":"integer","title":"Count"},"headline":{"type":"string","title":"Headline"},"appointment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Appointment Id"}},"type":"object","required":["kind","count","headline"],"title":"AttentionItemOut","description":"One line of his screen 12. `kind` is what it is; `headline` is what a person reads."},"AttributeTallyOut":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"times":{"type":"integer","title":"Times"}},"type":"object","required":["key","label","times"],"title":"AttributeTallyOut","description":"How often each chip was tapped. Beside the four metrics, not among them —\nhis decision 34 names exactly four, and a fifth added quietly is the drift\nthe decision exists to prevent."},"AuditEntryOut":{"properties":{"id":{"type":"integer","title":"Id"},"actor_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Actor Id"},"action":{"type":"string","title":"Action"},"entity_type":{"type":"string","title":"Entity Type"},"entity_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Entity Id"},"before_value":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Before Value"},"after_value":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"After Value"},"ip_address":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ip Address"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","actor_id","action","entity_type","entity_id","before_value","after_value","ip_address","created_at"],"title":"AuditEntryOut"},"AuditExportIn":{"properties":{"format":{"type":"string","enum":["csv","json"],"title":"Format","default":"csv"},"entity_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entity Type"},"entity_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Entity Id"},"actor_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Actor Id"},"action":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Action"},"since":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Since"},"until":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Until"}},"type":"object","title":"AuditExportIn"},"AuditExportOut":{"properties":{"url":{"type":"string","title":"Url"},"format":{"type":"string","title":"Format"},"rows":{"type":"integer","title":"Rows"},"generated_at":{"type":"string","format":"date-time","title":"Generated At"},"generated_by":{"type":"string","format":"uuid","title":"Generated By"},"filters":{"additionalProperties":true,"type":"object","title":"Filters"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"}},"type":"object","required":["url","format","rows","generated_at","generated_by","filters","expires_at"],"title":"AuditExportOut"},"AuthOut":{"properties":{"user":{"$ref":"#/components/schemas/UserOut"},"tokens":{"$ref":"#/components/schemas/TokenPair"},"second_factor_required":{"type":"boolean","title":"Second Factor Required","default":false},"referral":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Referral"}},"type":"object","required":["user","tokens"],"title":"AuthOut"},"AutomationTemplateOut":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"description":{"type":"string","title":"Description"},"always_on":{"type":"boolean","title":"Always On"},"enabled":{"type":"boolean","title":"Enabled"},"delay_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Delay Minutes"},"used":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Used"},"why_always_on":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Why Always On"}},"type":"object","required":["key","label","description","always_on","enabled"],"title":"AutomationTemplateOut"},"AutomationsIn":{"properties":{"review_request_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Review Request Enabled"},"review_request_delay_minutes":{"anyOf":[{"type":"integer","maximum":10080.0,"minimum":0.0},{"type":"null"}],"title":"Review Request Delay Minutes"}},"type":"object","title":"AutomationsIn"},"AutomationsOut":{"properties":{"business_id":{"type":"string","format":"uuid","title":"Business Id"},"templates":{"items":{"$ref":"#/components/schemas/AutomationTemplateOut"},"type":"array","title":"Templates"},"manual_review_requests":{"type":"integer","title":"Manual Review Requests"},"not_built":{"additionalProperties":{"type":"string"},"type":"object","title":"Not Built"}},"type":"object","required":["business_id","templates","manual_review_requests","not_built"],"title":"AutomationsOut"},"AvailabilityOut":{"properties":{"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"service_id":{"type":"string","format":"uuid","title":"Service Id"},"date":{"type":"string","format":"date","title":"Date"},"slot_interval_minutes":{"type":"integer","title":"Slot Interval Minutes","default":15},"slot_interval_source":{"type":"string","title":"Slot Interval Source","default":"platform"},"accepting_new_bookings":{"type":"boolean","title":"Accepting New Bookings","default":true},"location_operational_status":{"type":"string","title":"Location Operational Status","default":"active"},"closed_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Closed Reason"},"closes_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Closes At"},"timezone":{"type":"string","title":"Timezone"},"utc_offset_minutes":{"type":"integer","title":"Utc Offset Minutes"},"slots":{"items":{"$ref":"#/components/schemas/SlotOut"},"type":"array","title":"Slots","default":[]}},"type":"object","required":["branch_id","service_id","date","timezone","utc_offset_minutes"],"title":"AvailabilityOut"},"AvailabilityReplaceIn":{"properties":{"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"rules":{"items":{"$ref":"#/components/schemas/AvailabilityRuleIn"},"type":"array","title":"Rules"}},"type":"object","required":["branch_id"],"title":"AvailabilityReplaceIn","description":"The whole week at one branch, replaced in one call — a schedule is easier to\nreason about when it is stated in full rather than patched a row at a time."},"AvailabilityRuleIn":{"properties":{"weekday":{"type":"integer","maximum":6.0,"minimum":0.0,"title":"Weekday"},"starts_at":{"type":"string","format":"time","title":"Starts At"},"ends_at":{"type":"string","format":"time","title":"Ends At"},"is_active":{"type":"boolean","title":"Is Active","default":true}},"type":"object","required":["weekday","starts_at","ends_at"],"title":"AvailabilityRuleIn","description":"Local to the branch. weekday 0 = Sunday … 6 = Saturday."},"AvailabilityRuleOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"professional_id":{"type":"string","format":"uuid","title":"Professional Id"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"weekday":{"type":"integer","title":"Weekday"},"starts_at":{"type":"string","format":"time","title":"Starts At"},"ends_at":{"type":"string","format":"time","title":"Ends At"},"is_active":{"type":"boolean","title":"Is Active"}},"type":"object","required":["id","professional_id","branch_id","weekday","starts_at","ends_at","is_active"],"title":"AvailabilityRuleOut"},"BackAtOut":{"properties":{"after":{"type":"string","format":"date","title":"After"},"timezone":{"type":"string","title":"Timezone"},"back_at":{"anyOf":[{},{"type":"null"}],"title":"Back At"}},"type":"object","required":["after","timezone"],"title":"BackAtOut","description":"When they are back, derived (his §11). `back_at` is null when the schedule says nothing\nfor the next two weeks, which is honest and is not an error."},"BillingExceptionOut":{"properties":{"id":{"type":"string","title":"Id"},"kind":{"type":"string","title":"Kind"},"title":{"type":"string","title":"Title"},"subtitle":{"type":"string","title":"Subtitle"},"at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"At"},"amount_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Amount Cents"}},"type":"object","required":["id","kind","title","subtitle","at","amount_cents"],"title":"BillingExceptionOut"},"BlockIn":{"properties":{"kind":{"type":"string","enum":["intro","policy","procedure","warning","info"],"title":"Kind"},"title":{"type":"string","maxLength":160,"minLength":1,"title":"Title"},"body":{"type":"string","maxLength":20000,"minLength":1,"title":"Body"},"status":{"type":"string","enum":["complete","review_needed"],"title":"Status","default":"complete"}},"type":"object","required":["kind","title","body"],"title":"BlockIn"},"BlockOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"position":{"type":"integer","title":"Position"},"kind":{"type":"string","title":"Kind"},"title":{"type":"string","title":"Title"},"body":{"type":"string","title":"Body"},"status":{"type":"string","title":"Status"}},"type":"object","required":["id","position","kind","title","body","status"],"title":"BlockOut"},"Body_upload_v1_media_post":{"properties":{"kind":{"type":"string","title":"Kind","description":"user_avatar, business_logo, service_photo, …"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id","description":"required for business images"},"file":{"type":"string","contentMediaType":"application/octet-stream","title":"File"}},"type":"object","required":["kind","file"],"title":"Body_upload_v1_media_post"},"BookingUpdateOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"appointment_id":{"type":"string","format":"uuid","title":"Appointment Id"},"type":{"type":"string","title":"Type"},"estimated_delay_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Estimated Delay Minutes"},"message":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Message"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["id","appointment_id","type","created_at"],"title":"BookingUpdateOut"},"BranchCreateIn":{"properties":{"name":{"type":"string","maxLength":80,"minLength":1,"title":"Name"},"street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code"},"country":{"type":"string","title":"Country","default":"US"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"timezone":{"type":"string","title":"Timezone","default":"America/New_York"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"}},"type":"object","required":["name"],"title":"BranchCreateIn"},"BranchHoursIn":{"properties":{"weekday":{"type":"integer","maximum":6.0,"minimum":0.0,"title":"Weekday"},"opens_at":{"type":"string","format":"time","title":"Opens At"},"closes_at":{"type":"string","format":"time","title":"Closes At"}},"type":"object","required":["weekday","opens_at","closes_at"],"title":"BranchHoursIn","description":"Opening hours, local to the branch. weekday 0 = Sunday … 6 = Saturday."},"BranchHoursOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"weekday":{"type":"integer","title":"Weekday"},"opens_at":{"type":"string","format":"time","title":"Opens At"},"closes_at":{"type":"string","format":"time","title":"Closes At"}},"type":"object","required":["id","branch_id","weekday","opens_at","closes_at"],"title":"BranchHoursOut"},"BranchHoursReplaceIn":{"properties":{"hours":{"items":{"$ref":"#/components/schemas/BranchHoursIn"},"type":"array","title":"Hours"}},"type":"object","title":"BranchHoursReplaceIn"},"BranchOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"name":{"type":"string","title":"Name"},"street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code"},"country":{"type":"string","title":"Country"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"timezone":{"type":"string","title":"Timezone"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"cover_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Key"},"is_primary":{"type":"boolean","title":"Is Primary"},"is_active":{"type":"boolean","title":"Is Active"},"operational_status":{"type":"string","title":"Operational Status","default":"active"},"accepting_new_bookings":{"type":"boolean","title":"Accepting New Bookings","default":true},"operational_status_changed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Operational Status Changed At"},"operational_status_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Operational Status Reason"},"closure_effective_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Closure Effective At"},"slot_interval_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Slot Interval Minutes"}},"type":"object","required":["id","business_id","name","street","city","state","postal_code","country","latitude","longitude","timezone","phone","cover_key","is_primary","is_active"],"title":"BranchOut"},"BranchServiceIn":{"properties":{"price_cents":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Price Cents"},"is_offered":{"type":"boolean","title":"Is Offered","default":true}},"type":"object","title":"BranchServiceIn","description":"Per-branch override. price_cents None = inherit the business price."},"BranchServiceOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"service_id":{"type":"string","format":"uuid","title":"Service Id"},"price_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price Cents"},"is_offered":{"type":"boolean","title":"Is Offered"}},"type":"object","required":["id","branch_id","service_id","price_cents","is_offered"],"title":"BranchServiceOut"},"BranchUpdateIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":80,"minLength":1},{"type":"null"}],"title":"Name"},"street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"timezone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Timezone"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"cover_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Key"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"slot_interval_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Slot Interval Minutes"},"operational_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Operational Status"},"accepting_new_bookings":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Accepting New Bookings"},"operational_status_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Operational Status Reason"},"closure_effective_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Closure Effective At"}},"type":"object","title":"BranchUpdateIn"},"BusinessContextOut":{"properties":{"kind":{"type":"string","enum":["team_business","professional_in_business","independent"],"title":"Kind"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"business_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Name"},"business_status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Status"},"professional_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Professional Id"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"},"is_owner":{"type":"boolean","title":"Is Owner","default":false},"has_team":{"type":"boolean","title":"Has Team","default":false},"team":{"additionalProperties":{"type":"integer"},"type":"object","title":"Team"},"locations":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Locations"},"work_setups":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Work Setups"},"work_types":{"items":{"type":"string"},"type":"array","title":"Work Types"},"branch_ids":{"anyOf":[{"items":{"type":"string","format":"uuid"},"type":"array"},{"type":"null"}],"title":"Branch Ids"},"scope_locations":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Scope Locations"},"capabilities":{"items":{"type":"string"},"type":"array","title":"Capabilities"}},"type":"object","required":["kind"],"title":"BusinessContextOut","description":"One My Business context — his v1.3 §41, resolved by the platform.\n\n`kind` is team_business (a business this person owns), professional_in_business (one they work\nat) or independent (their own operation, with no business row). `has_team` false is his §11\nand §44 together: the shell hides Team Management instead of drawing a team of nobody.\n`branch_ids` null means the whole business, exactly as the access rules read it, and\n`scope_locations` names those locations for his header. `work_types` is how an independent\nworks on their own. Facts and capabilities: no money rides on a context (his §40)."},"BusinessCreateIn":{"properties":{"name":{"type":"string","maxLength":120,"minLength":2,"title":"Name"},"slug":{"type":"string","maxLength":80,"minLength":2,"pattern":"^[a-z0-9][a-z0-9-]*$","title":"Slug"},"tagline":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}],"title":"Tagline"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"branch_name":{"type":"string","maxLength":80,"minLength":1,"title":"Branch Name","default":"Main"},"street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code"},"country":{"type":"string","title":"Country","default":"US"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"timezone":{"type":"string","title":"Timezone","default":"America/New_York"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"}},"type":"object","required":["name","slug"],"title":"BusinessCreateIn","description":"Creating a business also creates its organization and its first branch —\na brand always has at least one place where people are served."},"BusinessDetailOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"organization_id":{"type":"string","format":"uuid","title":"Organization Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"tagline":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tagline"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"status":{"type":"string","title":"Status"},"is_verified":{"type":"boolean","title":"Is Verified"},"verification_status":{"type":"string","title":"Verification Status","default":"unverified"},"logo_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Key"},"cover_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Key"},"public_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Public Email"},"public_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Public Phone"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"},"established_year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Established Year"},"languages":{"items":{"type":"string"},"type":"array","title":"Languages","default":[]},"service_areas":{"items":{"type":"string"},"type":"array","title":"Service Areas","default":[]},"rating_avg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rating Avg"},"rating_count":{"type":"integer","title":"Rating Count"},"show_exact_stock":{"type":"boolean","title":"Show Exact Stock","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At"},"branches":{"items":{"$ref":"#/components/schemas/BranchOut"},"type":"array","title":"Branches","default":[]},"category_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Slug"},"category_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Name"},"is_open_now":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Open Now"},"verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Verified At"}},"type":"object","required":["id","organization_id","slug","name","tagline","description","status","is_verified","logo_key","cover_key","rating_count","created_at"],"title":"BusinessDetailOut"},"BusinessMembershipsStateOut":{"properties":{"can_sell":{"type":"boolean","title":"Can Sell"},"requires":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Requires"},"plans":{"items":{"$ref":"#/components/schemas/BusinessPlanOut"},"type":"array","title":"Plans","default":[]}},"type":"object","required":["can_sell"],"title":"BusinessMembershipsStateOut","description":"The owner's Memberships screen in one answer.\n\n`can_sell` is the owner's §2 gate — \"Professional Plus / Commercial …habilita\nlas herramientas comerciales adicionales definidas para: Shop + Memberships\".\nIt is carried alongside the plans because an empty list on its own is\nindistinguishable from a shop that never made one, and the owner would go\nlooking for a bug instead of for his subscription.\n\n`requires` names the tool the plan must unlock, not a price. The price is\nconfiguration (§1/§2: \"el precio NO debe estar hard-coded\"), so it is read from\nGET /v1/billing/plans and never quoted here."},"BusinessOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"organization_id":{"type":"string","format":"uuid","title":"Organization Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"tagline":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tagline"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"status":{"type":"string","title":"Status"},"is_verified":{"type":"boolean","title":"Is Verified"},"verification_status":{"type":"string","title":"Verification Status","default":"unverified"},"logo_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Key"},"cover_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Key"},"public_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Public Email"},"public_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Public Phone"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"},"established_year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Established Year"},"languages":{"items":{"type":"string"},"type":"array","title":"Languages","default":[]},"service_areas":{"items":{"type":"string"},"type":"array","title":"Service Areas","default":[]},"rating_avg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rating Avg"},"rating_count":{"type":"integer","title":"Rating Count"},"show_exact_stock":{"type":"boolean","title":"Show Exact Stock","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","organization_id","slug","name","tagline","description","status","is_verified","logo_key","cover_key","rating_count","created_at"],"title":"BusinessOut"},"BusinessPlanCreateIn":{"properties":{"code":{"type":"string","maxLength":60,"minLength":2,"pattern":"^[A-Za-z0-9][A-Za-z0-9_-]*$","title":"Code"},"name":{"type":"string","maxLength":120,"minLength":2,"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"price_cents":{"type":"integer","minimum":0.0,"title":"Price Cents"},"billing_period":{"type":"string","enum":["monthly","quarterly","yearly"],"title":"Billing Period","default":"monthly"},"benefits":{"additionalProperties":true,"type":"object","title":"Benefits"},"image_key":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Image Key"},"is_active":{"type":"boolean","title":"Is Active","default":false},"audience":{"type":"string","maxLength":20,"title":"Audience","default":"client"}},"type":"object","required":["code","name","price_cents"],"title":"BusinessPlanCreateIn","description":"A membership a business creates for its own clients.\n\n`benefits` is free-form on purpose — \"determinados cortes, servicios,\nprioridad de reserva o beneficios\" is his own list of examples, not an\nenumeration, and a fixed schema here would cap what a business may offer.\nThree keys are refused (`discount_bps`, `approved_by`, `unlocks`): they are\nnot descriptions of the business's product but claims on MyLook's. See\nbusiness_memberships.RESERVED_BENEFIT_KEYS."},"BusinessPlanOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"code":{"type":"string","title":"Code"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"audience":{"type":"string","title":"Audience"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"price_cents":{"type":"integer","title":"Price Cents"},"billing_period":{"type":"string","title":"Billing Period"},"benefits":{"additionalProperties":true,"type":"object","title":"Benefits","default":{}},"image_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Key"},"is_active":{"type":"boolean","title":"Is Active"},"is_sellable":{"type":"boolean","title":"Is Sellable"},"withdrawn_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Withdrawn Reason"},"member_count":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Member Count"}},"type":"object","required":["id","code","name","description","audience","business_id","price_cents","billing_period","is_active","is_sellable"],"title":"BusinessPlanOut","description":"A business's membership, with the two facts PlanOut has no room for.\n\n`business_id` is never null here — that is what distinguishes it from a\nMyLook-wide plan — and `is_sellable` is what says whether it may still be\nJOINED, which is a different question from whether it exists."},"BusinessPlanUpdateIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":120,"minLength":2},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"price_cents":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Price Cents"},"billing_period":{"anyOf":[{"type":"string","enum":["monthly","quarterly","yearly"]},{"type":"null"}],"title":"Billing Period"},"benefits":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Benefits"},"image_key":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Image Key"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"is_sellable":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Sellable"}},"type":"object","title":"BusinessPlanUpdateIn","description":"Edit one. `code`, `audience` and the owning business are absent on purpose —\na code is what a receipt refers to, and the other two are not commercial fields\nat all. A different product is a different plan."},"BusinessReviewOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"organization_id":{"type":"string","format":"uuid","title":"Organization Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"tagline":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tagline"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"status":{"type":"string","title":"Status"},"is_verified":{"type":"boolean","title":"Is Verified"},"verification_status":{"type":"string","title":"Verification Status","default":"unverified"},"logo_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Key"},"cover_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Key"},"public_email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Public Email"},"public_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Public Phone"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"},"established_year":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Established Year"},"languages":{"items":{"type":"string"},"type":"array","title":"Languages","default":[]},"service_areas":{"items":{"type":"string"},"type":"array","title":"Service Areas","default":[]},"rating_avg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rating Avg"},"rating_count":{"type":"integer","title":"Rating Count"},"show_exact_stock":{"type":"boolean","title":"Show Exact Stock","default":false},"created_at":{"type":"string","format":"date-time","title":"Created At"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"branch_count":{"type":"integer","title":"Branch Count","default":0},"last_action":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Action"},"last_action_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Action At"},"last_action_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Action Reason"}},"type":"object","required":["id","organization_id","slug","name","tagline","description","status","is_verified","logo_key","cover_key","rating_count","created_at"],"title":"BusinessReviewOut","description":"One row of the staff review queue.\n\nCarries where the business is, because \"Verify Barbershop\" is not something\nanybody can make a decision about, and the last decision taken on it, so a\nreviewer does not re-decide what a colleague settled yesterday."},"BusinessSearchOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"tagline":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tagline"},"logo_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Key"},"cover_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Key"},"rating_avg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rating Avg"},"rating_count":{"type":"integer","title":"Rating Count"},"is_verified":{"type":"boolean","title":"Is Verified"},"category_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Slug"},"category_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Name"},"price_from_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price From Cents"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"branch_name":{"type":"string","title":"Branch Name"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"distance_miles":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance Miles"},"is_open_now":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Open Now"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"},"matched_service":{"anyOf":[{"$ref":"#/components/schemas/MatchedServiceOut"},{"type":"null"}]},"next_available_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Available At"},"next_available_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Available Label"}},"type":"object","required":["id","slug","name","tagline","logo_key","cover_key","rating_avg","rating_count","is_verified","category_slug","category_name","price_from_cents","branch_id","branch_name","city","state","latitude","longitude","distance_miles","is_open_now"],"title":"BusinessSearchOut","description":"One card on the Search screen.\n\nDeliberately flat and complete: everything the card draws comes from this one\nresponse, so a list of twenty businesses is one request rather than twenty-one."},"BusinessSocialIn":{"properties":{"instagram":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instagram"},"tiktok":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tiktok"},"facebook":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Facebook"},"youtube":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Youtube"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"}},"type":"object","title":"BusinessSocialIn","description":"His five, all optional. A platform sent as null or \"\" is disconnected - the same\ncontract as his ONB-012, so one screen can serve a professional and a shop."},"BusinessSocialOut":{"properties":{"platform":{"type":"string","enum":["instagram","tiktok","facebook","youtube","website"],"title":"Platform"},"handle":{"type":"string","title":"Handle"}},"type":"object","required":["platform","handle"],"title":"BusinessSocialOut"},"BusinessSubscribeIn":{"properties":{"plan_id":{"type":"string","format":"uuid","title":"Plan Id"},"card_number":{"anyOf":[{"type":"string","maxLength":25},{"type":"null"}],"title":"Card Number"}},"type":"object","required":["plan_id"],"title":"BusinessSubscribeIn"},"BusinessUpdateIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":120,"minLength":2},{"type":"null"}],"title":"Name"},"tagline":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}],"title":"Tagline"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"primary_category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Primary Category Id"},"logo_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Key"},"cover_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Key"},"show_exact_stock":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Show Exact Stock"},"public_email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Public Email"},"public_phone":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Public Phone"},"website":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Website"},"established_year":{"anyOf":[{"type":"integer","maximum":2100.0,"minimum":1800.0},{"type":"null"}],"title":"Established Year"},"languages":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":12},{"type":"null"}],"title":"Languages"},"service_areas":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":25},{"type":"null"}],"title":"Service Areas"},"status":{"anyOf":[{"type":"string","enum":["draft","active"]},{"type":"null"}],"title":"Status"},"slot_interval_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Slot Interval Minutes"}},"type":"object","title":"BusinessUpdateIn","description":"Everything about a business that can change after it is created.\n\nEvery field is optional, and OMITTING one means \"leave it alone\" while sending\nnull means \"clear it\". They are different requests, so a client can remove a\nlogo without resending the whole profile, and can change one line without\naccidentally erasing the rest.\n\nslug is deliberately absent. It is the public URL people share and search\nengines index; changing it silently breaks every link that already exists, so\nit is a support action rather than a form field."},"BusinessVerificationOut":{"properties":{"business_id":{"type":"string","format":"uuid","title":"Business Id"},"is_verified":{"type":"boolean","title":"Is Verified"},"verification_status":{"type":"string","title":"Verification Status"},"verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Verified At"},"checks":{"items":{"$ref":"#/components/schemas/VerificationCheckOut"},"type":"array","title":"Checks"},"changes_requested":{"anyOf":[{"$ref":"#/components/schemas/ChangesRequestedOut"},{"type":"null"}]},"escalation":{"anyOf":[{"$ref":"#/components/schemas/EscalationOut"},{"type":"null"}]}},"type":"object","required":["business_id","is_verified","verification_status","checks"],"title":"BusinessVerificationOut"},"CancelIn":{"properties":{"reason":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Reason"}},"type":"object","title":"CancelIn"},"CartItemIn":{"properties":{"product_id":{"type":"string","format":"uuid","title":"Product Id"},"quantity":{"type":"integer","maximum":99.0,"minimum":1.0,"title":"Quantity","default":1},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"variant_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Variant Id"},"variants":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Variants","default":[]},"variant_attribute":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Variant Attribute"}},"type":"object","required":["product_id"],"title":"CartItemIn","description":"Add to Cart. A product, how many, and which location — nothing else.\n\nThere is deliberately no price field. If an app sends one it is ignored: the\nprice is read from the shop's own catalogue, and `cart_items` has no column\nto write a caller's number into even if somebody wanted to."},"CartLineOut":{"properties":{"item_id":{"type":"string","format":"uuid","title":"Item Id"},"product_id":{"type":"string","format":"uuid","title":"Product Id"},"variant_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Variant Id"},"variant_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Variant Label"},"name":{"type":"string","title":"Name"},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand"},"image_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Key"},"unit_price_cents":{"type":"integer","title":"Unit Price Cents"},"quantity":{"type":"integer","title":"Quantity"},"line_total_cents":{"type":"integer","title":"Line Total Cents"},"in_stock":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"In Stock"}},"type":"object","required":["item_id","product_id","name","brand","image_key","unit_price_cents","quantity","line_total_cents"],"title":"CartLineOut"},"CartOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"business_name":{"type":"string","title":"Business Name"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"branch_name":{"type":"string","title":"Branch Name"},"currency":{"type":"string","title":"Currency"},"status":{"type":"string","title":"Status"},"items":{"items":{"$ref":"#/components/schemas/CartLineOut"},"type":"array","title":"Items"},"item_count":{"type":"integer","title":"Item Count"},"subtotal_cents":{"type":"integer","title":"Subtotal Cents"},"discount_cents":{"type":"integer","title":"Discount Cents","default":0},"membership_plan_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Membership Plan Name"},"fee_cents":{"type":"integer","title":"Fee Cents"},"tax_cents":{"type":"integer","title":"Tax Cents"},"total_cents":{"type":"integer","title":"Total Cents"}},"type":"object","required":["id","business_id","business_name","branch_id","branch_name","currency","status","items","item_count","subtotal_cents","fee_cents","tax_cents","total_cents"],"title":"CartOut"},"CartQuantityIn":{"properties":{"quantity":{"type":"integer","maximum":99.0,"minimum":0.0,"title":"Quantity"}},"type":"object","required":["quantity"],"title":"CartQuantityIn","description":"An absolute quantity, not a delta. Zero removes the line."},"CaseDetailOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"case_number":{"type":"string","title":"Case Number"},"category":{"type":"string","title":"Category"},"subtype":{"type":"string","title":"Subtype"},"subject":{"type":"string","title":"Subject"},"description":{"type":"string","title":"Description"},"status":{"type":"string","title":"Status"},"waiting_on":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Waiting On"},"priority":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Priority"},"impact":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Impact"},"impact_amount_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Impact Amount Cents"},"currency":{"type":"string","title":"Currency"},"source":{"type":"string","title":"Source"},"channel":{"type":"string","title":"Channel"},"language":{"type":"string","title":"Language"},"customer":{"anyOf":[{"$ref":"#/components/schemas/malu__domains__support__schemas__PersonOut"},{"type":"null"}]},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"business_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Name"},"business_city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business City"},"business_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business State"},"appointment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Appointment Id"},"order_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Order Id"},"payment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Payment Id"},"review_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Review Id"},"subscription_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Subscription Id"},"assignee":{"anyOf":[{"$ref":"#/components/schemas/AssigneeOut"},{"type":"null"}]},"sla_goal_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sla Goal Minutes"},"sla_due_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sla Due At"},"sla_remaining_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sla Remaining Seconds"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"resolution":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution"},"resolution_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution Note"},"resolved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Resolved At"},"last_event_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Event Title"},"last_event_at":{"type":"string","format":"date-time","title":"Last Event At"},"event_count":{"type":"integer","title":"Event Count"},"message_count":{"type":"integer","title":"Message Count"},"evidence_count":{"type":"integer","title":"Evidence Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"events":{"items":{"$ref":"#/components/schemas/malu__domains__support__schemas__EventOut"},"type":"array","title":"Events"},"messages":{"items":{"$ref":"#/components/schemas/malu__domains__support__schemas__MessageOut"},"type":"array","title":"Messages"},"evidence":{"items":{"$ref":"#/components/schemas/malu__domains__support__schemas__EvidenceOut"},"type":"array","title":"Evidence"}},"type":"object","required":["id","case_number","category","subtype","subject","description","status","waiting_on","priority","impact","impact_amount_cents","currency","source","channel","language","customer","business_id","business_name","business_city","business_state","appointment_id","order_id","payment_id","review_id","subscription_id","assignee","sla_goal_minutes","sla_due_at","sla_remaining_seconds","tags","resolution","resolution_note","resolved_at","last_event_title","last_event_at","event_count","message_count","evidence_count","created_at","updated_at","events","messages","evidence"],"title":"CaseDetailOut"},"CaseOpenIn":{"properties":{"category":{"anyOf":[{"type":"string","enum":["booking","payments","orders","accounts","safety_fraud","reviews"]},{"type":"null"}],"title":"Category"},"subtype":{"type":"string","maxLength":80,"minLength":2,"title":"Subtype"},"subject":{"type":"string","maxLength":160,"minLength":3,"title":"Subject"},"description":{"type":"string","maxLength":4000,"minLength":10,"title":"Description"},"appointment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Appointment Id"},"order_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Order Id"},"payment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Payment Id"},"review_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Review Id"},"subscription_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Subscription Id"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"}},"type":"object","required":["subtype","subject","description"],"title":"CaseOpenIn","description":"A case is about ONE thing — an appointment, an order, a payment, a review, a\nmembership, a business, or the person's own account. The platform reads who the\nparties are from that thing; the opener never names them."},"CaseOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"case_number":{"type":"string","title":"Case Number"},"category":{"type":"string","title":"Category"},"subtype":{"type":"string","title":"Subtype"},"subject":{"type":"string","title":"Subject"},"description":{"type":"string","title":"Description"},"status":{"type":"string","title":"Status"},"waiting_on":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Waiting On"},"priority":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Priority"},"impact":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Impact"},"impact_amount_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Impact Amount Cents"},"currency":{"type":"string","title":"Currency"},"source":{"type":"string","title":"Source"},"channel":{"type":"string","title":"Channel"},"language":{"type":"string","title":"Language"},"customer":{"anyOf":[{"$ref":"#/components/schemas/malu__domains__support__schemas__PersonOut"},{"type":"null"}]},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"business_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Name"},"business_city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business City"},"business_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business State"},"appointment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Appointment Id"},"order_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Order Id"},"payment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Payment Id"},"review_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Review Id"},"subscription_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Subscription Id"},"assignee":{"anyOf":[{"$ref":"#/components/schemas/AssigneeOut"},{"type":"null"}]},"sla_goal_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sla Goal Minutes"},"sla_due_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Sla Due At"},"sla_remaining_seconds":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sla Remaining Seconds"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"resolution":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution"},"resolution_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution Note"},"resolved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Resolved At"},"last_event_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Event Title"},"last_event_at":{"type":"string","format":"date-time","title":"Last Event At"},"event_count":{"type":"integer","title":"Event Count"},"message_count":{"type":"integer","title":"Message Count"},"evidence_count":{"type":"integer","title":"Evidence Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","case_number","category","subtype","subject","description","status","waiting_on","priority","impact","impact_amount_cents","currency","source","channel","language","customer","business_id","business_name","business_city","business_state","appointment_id","order_id","payment_id","review_id","subscription_id","assignee","sla_goal_minutes","sla_due_at","sla_remaining_seconds","tags","resolution","resolution_note","resolved_at","last_event_title","last_event_at","event_count","message_count","evidence_count","created_at","updated_at"],"title":"CaseOut"},"CasePageOut":{"properties":{"items":{"items":{"$ref":"#/components/schemas/CaseOut"},"type":"array","title":"Items"},"next_cursor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Next Cursor"},"has_more":{"type":"boolean","title":"Has More"}},"type":"object","required":["items","next_cursor","has_more"],"title":"CasePageOut","description":"One page of the Case Queue — his approval of Option A, 2026-09-10.\n\n`next_cursor` is opaque and null only on the last page. `has_more` says the\nsame thing in a form a screen can ask directly, instead of having to know\nthat \"is there more?\" is answered by checking a field for null."},"CategoryOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"parent_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Parent Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"sort_order":{"type":"integer","title":"Sort Order"},"is_business_type":{"type":"boolean","title":"Is Business Type","default":false}},"type":"object","required":["id","parent_id","slug","name","sort_order"],"title":"CategoryOut"},"CategoryTreeOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"parent_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Parent Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"sort_order":{"type":"integer","title":"Sort Order"},"is_business_type":{"type":"boolean","title":"Is Business Type","default":false},"children":{"items":{"$ref":"#/components/schemas/CategoryOut"},"type":"array","title":"Children","default":[]}},"type":"object","required":["id","parent_id","slug","name","sort_order"],"title":"CategoryTreeOut"},"ChangesRequestedOut":{"properties":{"reason":{"type":"string","title":"Reason"},"at":{"type":"string","format":"date-time","title":"At"}},"type":"object","required":["reason","at"],"title":"ChangesRequestedOut"},"ChannelRuleIn":{"properties":{"email_enabled":{"type":"boolean","title":"Email Enabled"}},"type":"object","required":["email_enabled"],"title":"ChannelRuleIn"},"ChannelRuleOut":{"properties":{"kind":{"type":"string","title":"Kind"},"email_enabled":{"type":"boolean","title":"Email Enabled"}},"type":"object","required":["kind","email_enabled"],"title":"ChannelRuleOut"},"CheckDecisionIn":{"properties":{"reason":{"type":"string","maxLength":500,"minLength":3,"title":"Reason","description":"Why this decision was taken. Kept forever, against the staff member who took it."},"decision":{"type":"string","enum":["verified","rejected","changes_requested"],"title":"Decision"}},"type":"object","required":["reason","decision"],"title":"CheckDecisionIn"},"CheckDocumentIn":{"properties":{"media_key":{"type":"string","maxLength":300,"minLength":3,"title":"Media Key","description":"The key returned by POST /media for kind verification_document."},"name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Name","description":"What to call the file. Defaults to his Documents list's name."}},"type":"object","required":["media_key"],"title":"CheckDocumentIn"},"CheckpointIn":{"properties":{"checkpoint":{"anyOf":[{"type":"string","maxLength":60},{"type":"null"}],"title":"Checkpoint"}},"type":"object","title":"CheckpointIn","description":"HIS §63 — where somebody got to, so a relaunch does not start at Welcome again."},"CheckpointOut":{"properties":{"checkpoint":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Checkpoint"},"at":{"anyOf":[{},{"type":"null"}],"title":"At"}},"type":"object","title":"CheckpointOut"},"ClaimCreateIn":{"properties":{"contact_name":{"type":"string","maxLength":120,"minLength":2,"title":"Contact Name"},"contact_phone":{"type":"string","maxLength":40,"minLength":5,"title":"Contact Phone"},"claimant_role":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Claimant Role"},"note":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Note"},"evidence":{"items":{"$ref":"#/components/schemas/malu__domains__directory__schemas__EvidenceIn"},"type":"array","maxItems":10,"title":"Evidence"}},"type":"object","required":["contact_name","contact_phone"],"title":"ClaimCreateIn"},"ClaimOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"listing_id":{"type":"string","format":"uuid","title":"Listing Id"},"claimant_id":{"type":"string","format":"uuid","title":"Claimant Id"},"contact_name":{"type":"string","title":"Contact Name"},"contact_phone":{"type":"string","title":"Contact Phone"},"claimant_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claimant Role"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"status":{"type":"string","title":"Status"},"analyzer_engine":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Analyzer Engine"},"analyzer_confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Analyzer Confidence"},"analyzer_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Analyzer Reason"},"analyzer_extracted":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Analyzer Extracted"},"decided_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Decided At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"evidence":{"items":{"$ref":"#/components/schemas/malu__domains__directory__schemas__EvidenceOut"},"type":"array","title":"Evidence","default":[]},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"}},"type":"object","required":["id","listing_id","claimant_id","contact_name","contact_phone","claimant_role","note","status","analyzer_engine","analyzer_confidence","analyzer_reason","analyzer_extracted","decided_at","created_at"],"title":"ClaimOut"},"ClaimRejectIn":{"properties":{"reason":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Reason"}},"type":"object","title":"ClaimRejectIn"},"ClaimReviewOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"listing_id":{"type":"string","format":"uuid","title":"Listing Id"},"claimant_id":{"type":"string","format":"uuid","title":"Claimant Id"},"contact_name":{"type":"string","title":"Contact Name"},"contact_phone":{"type":"string","title":"Contact Phone"},"claimant_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Claimant Role"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"status":{"type":"string","title":"Status"},"analyzer_engine":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Analyzer Engine"},"analyzer_confidence":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Analyzer Confidence"},"analyzer_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Analyzer Reason"},"analyzer_extracted":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Analyzer Extracted"},"decided_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Decided At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"evidence":{"items":{"$ref":"#/components/schemas/malu__domains__directory__schemas__EvidenceOut"},"type":"array","title":"Evidence","default":[]},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"listing_name":{"type":"string","title":"Listing Name"},"listing_city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Listing City"},"listing_state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Listing State"},"listing_status":{"type":"string","title":"Listing Status"}},"type":"object","required":["id","listing_id","claimant_id","contact_name","contact_phone","claimant_role","note","status","analyzer_engine","analyzer_confidence","analyzer_reason","analyzer_extracted","decided_at","created_at","listing_name","listing_city","listing_state","listing_status"],"title":"ClaimReviewOut","description":"The admin queue row: the claim plus enough of the listing to judge it\nwithout a second request."},"ClientCreateIn":{"properties":{"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"full_name":{"anyOf":[{"type":"string","maxLength":120,"minLength":2},{"type":"null"}],"title":"Full Name"},"phone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Phone"},"email":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Email"},"basis":{"anyOf":[{"type":"string","maxLength":300,"minLength":3},{"type":"null"}],"title":"Basis"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"}},"type":"object","title":"ClientCreateIn","description":"His decision 54. EITHER somebody the shop knows by account (`user_id` —\nthey booked; the booking is the basis) OR a new person by name and contact,\nwith the shop's own `basis`: why it holds their details."},"ClientNoteIn":{"properties":{"body":{"type":"string","maxLength":2000,"minLength":1,"title":"Body"}},"type":"object","required":["body"],"title":"ClientNoteIn"},"ClientNoteOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_client_id":{"type":"string","format":"uuid","title":"Business Client Id"},"author_id":{"type":"string","format":"uuid","title":"Author Id"},"body":{"type":"string","title":"Body"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","business_client_id","author_id","body","created_at"],"title":"ClientNoteOut"},"ClientRecordOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"full_name":{"type":"string","title":"Full Name"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"basis":{"type":"string","title":"Basis"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","business_id","user_id","full_name","phone","email","basis","created_at"],"title":"ClientRecordOut"},"ClientRowOut":{"properties":{"client_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Client User Id"},"name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Name"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"first_seen_at":{"type":"string","format":"date-time","title":"First Seen At"},"first_visit_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"First Visit At"},"last_visit_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Visit At"},"next_appointment_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Next Appointment At"},"visits_completed":{"type":"integer","title":"Visits Completed","default":0},"cancellations":{"type":"integer","title":"Cancellations","default":0},"cancelled_by_shop":{"type":"integer","title":"Cancelled By Shop","default":0},"no_shows":{"type":"integer","title":"No Shows","default":0},"upcoming":{"type":"integer","title":"Upcoming","default":0},"favorite_service_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Favorite Service Name"},"favorite_professional_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Favorite Professional Name"},"total_spent_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Spent Cents"},"business_client_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Client Id"},"record_branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Record Branch Id"},"has_account":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Has Account","default":true},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"basis":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Basis"},"notes_count":{"type":"integer","title":"Notes Count","default":0},"avg_days_between_visits":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Avg Days Between Visits"},"rebooked_within_30d":{"type":"boolean","title":"Rebooked Within 30D","default":false},"at_risk":{"type":"boolean","title":"At Risk","default":false},"due_for_rebooking":{"type":"boolean","title":"Due For Rebooking","default":false}},"type":"object","required":["first_seen_at"],"title":"ClientRowOut","description":"One person this shop has served, derived from its own appointments.\n\nNOT A ROW SOMEBODY TYPED. There is no client table and no \"add client\",\nbecause a list that can be typed into drifts from the bookings it describes."},"ClientUpdateIn":{"properties":{"full_name":{"anyOf":[{"type":"string","maxLength":120,"minLength":2},{"type":"null"}],"title":"Full Name"},"phone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Phone"},"email":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Email"},"basis":{"anyOf":[{"type":"string","maxLength":300,"minLength":3},{"type":"null"}],"title":"Basis"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"reason":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Reason"}},"type":"object","title":"ClientUpdateIn"},"ConnectedAccountOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"status":{"type":"string","title":"Status"},"charges_enabled":{"type":"boolean","title":"Charges Enabled"},"payouts_enabled":{"type":"boolean","title":"Payouts Enabled"},"details_submitted":{"type":"boolean","title":"Details Submitted"},"can_receive":{"type":"boolean","title":"Can Receive"},"requirements":{"additionalProperties":true,"type":"object","title":"Requirements"},"provider_account_id":{"type":"string","title":"Provider Account Id"}},"type":"object","required":["id","status","charges_enabled","payouts_enabled","details_submitted","can_receive","requirements","provider_account_id"],"title":"ConnectedAccountOut","description":"A shop's payout account, and whether money can actually reach it.\n\n`can_receive` is the answer a screen should act on, and it is BOTH\ncapabilities rather than either: an account that can be charged into but not\npaid out of accumulates a balance nobody can withdraw, which is worse for\nthe shop than being told it is not ready yet.\n\n`requirements` is the processor's own list of what is still outstanding,\npassed through verbatim so \"your payouts are paused\" arrives with the reason\nattached instead of a shrug."},"ContextIn":{"properties":{"context":{"type":"string","enum":["client","professional"],"title":"Context"}},"type":"object","required":["context"],"title":"ContextIn"},"ContextOut":{"properties":{"available":{"items":{"type":"string"},"type":"array","title":"Available"},"active":{"type":"string","title":"Active"},"resolved_from":{"type":"string","title":"Resolved From"}},"type":"object","required":["available","active","resolved_from"],"title":"ContextOut","description":"Everything the app needs to open the right surface, and to say why."},"ContextSwitchOut":{"properties":{"from_context":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Context"},"to_context":{"type":"string","title":"To Context"},"at":{"title":"At"}},"type":"object","required":["to_context","at"],"title":"ContextSwitchOut","description":"HIS §61's ACCOUNT_CONTEXT_SWITCHED. \"No need to expose this to user.\" So it carries no\nmessage and no wording for a screen: it is for audit, restoration and analytics."},"ConversationOpenIn":{"properties":{"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"appointment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Appointment Id"},"subject":{"anyOf":[{"type":"string","maxLength":160},{"type":"null"}],"title":"Subject"}},"type":"object","required":["branch_id"],"title":"ConversationOpenIn"},"ConversationOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"client_user_id":{"type":"string","format":"uuid","title":"Client User Id"},"appointment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Appointment Id"},"subject":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subject"},"last_message_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Message At"},"is_archived":{"type":"boolean","title":"Is Archived"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"business_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Name"},"branch_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch Name"},"client_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Name"},"last_message_body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Message Body"},"last_message_sender_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Last Message Sender Id"},"unread_count":{"type":"integer","title":"Unread Count","default":0}},"type":"object","required":["id","branch_id","client_user_id","appointment_id","subject","last_message_at","is_archived","created_at"],"title":"ConversationOut"},"DataRequestOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"kind":{"type":"string","title":"Kind"},"status":{"type":"string","title":"Status"},"requested_ip":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Requested Ip"},"session_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Session Id"},"summary":{"additionalProperties":true,"type":"object","title":"Summary"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"}},"type":"object","required":["id","user_id","kind","status","requested_ip","session_id","summary","created_at","completed_at"],"title":"DataRequestOut","description":"One row of the register — DOC-002 page 4 §11.6, Compliance Management."},"DayBlockOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"starts_at":{"title":"Starts At"},"ends_at":{"title":"Ends At"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"all_day":{"type":"boolean","title":"All Day","default":false},"whole_location":{"type":"boolean","title":"Whole Location","default":false},"type_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type Code"},"chosen_all_day":{"type":"boolean","title":"Chosen All Day","default":false}},"type":"object","required":["id","branch_id","starts_at","ends_at"],"title":"DayBlockOut","description":"An exception on the day - his §8. It never changes the base schedule."},"DayBookingOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"reference":{"type":"string","title":"Reference"},"starts_at":{"title":"Starts At"},"ends_at":{"title":"Ends At"},"status":{"type":"string","title":"Status"},"service_name":{"type":"string","title":"Service Name"},"client_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Name"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"price_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price Cents"},"location_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Location Name"},"source":{"type":"string","title":"Source"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"has_client_note":{"type":"boolean","title":"Has Client Note","default":false},"running_late":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Running Late"}},"type":"object","required":["id","reference","starts_at","ends_at","status","service_name","duration_minutes","source"],"title":"DayBookingOut","description":"One booking on a professional's own day. `id` is the canonical booking id every other\nsurface uses - his §3, \"ONE BOOKING = ONE BOOKING ID\"."},"DayOffOut":{"properties":{"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"all_day":{"type":"boolean","title":"All Day","default":false},"starts_at":{"anyOf":[{},{"type":"null"}],"title":"Starts At"},"ends_at":{"anyOf":[{},{"type":"null"}],"title":"Ends At"},"back_at":{"anyOf":[{},{"type":"null"}],"title":"Back At"}},"type":"object","title":"DayOffOut","description":"His §53 and §54: a day somebody is not working says so, and says when they are back.\n`back_at` is DERIVED from the block's end plus the next base period (his §11)."},"DevicePlatform":{"type":"string","enum":["ios","android","web"],"title":"DevicePlatform"},"DeviceTokenIn":{"properties":{"token":{"type":"string","maxLength":512,"minLength":8,"title":"Token"},"platform":{"$ref":"#/components/schemas/DevicePlatform"}},"type":"object","required":["token","platform"],"title":"DeviceTokenIn"},"DeviceTokenOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"token":{"type":"string","title":"Token"},"platform":{"$ref":"#/components/schemas/DevicePlatform"},"last_seen_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Seen At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","user_id","token","platform","last_seen_at","created_at"],"title":"DeviceTokenOut"},"DisputeLiabilityPreviewOut":{"properties":{"dispute_id":{"type":"string","format":"uuid","title":"Dispute Id"},"rule":{"type":"string","title":"Rule"},"amount_cents":{"type":"integer","title":"Amount Cents"},"basis":{"type":"string","title":"Basis"},"shares":{"items":{"$ref":"#/components/schemas/DisputeShareOut"},"type":"array","title":"Shares"},"unattributed_cents":{"type":"integer","title":"Unattributed Cents"},"blocked_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Blocked Reason"},"settled":{"type":"boolean","title":"Settled"},"fee_cents":{"type":"integer","title":"Fee Cents","default":0},"tax_deferred_cents":{"type":"integer","title":"Tax Deferred Cents","default":0},"tax_liability":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tax Liability"},"tax_basis":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tax Basis"},"commission_reversed_cents":{"type":"integer","title":"Commission Reversed Cents","default":0},"commission_basis":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Commission Basis"}},"type":"object","required":["dispute_id","rule","amount_cents","basis","shares","unattributed_cents","blocked_reason","settled"],"title":"DisputeLiabilityPreviewOut","description":"What losing this dispute WOULD cost each party, computed now.\n\nThe same resolution the settlement will run, so the screen a staff member\ndecides from cannot disagree with what then happens — the discipline\nRefundPreviewOut already follows."},"DisputeOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"payment_id":{"type":"string","format":"uuid","title":"Payment Id"},"provider_dispute_id":{"type":"string","title":"Provider Dispute Id"},"amount_cents":{"type":"integer","title":"Amount Cents"},"currency":{"type":"string","title":"Currency"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"status":{"type":"string","title":"Status"},"evidence_due_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Evidence Due At"},"liability":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Liability"},"liability_basis":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Liability Basis"},"liability_decided_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Liability Decided By"},"liability_decided_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Liability Decided At"},"liability_settled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Liability Settled At"},"fee_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fee Cents"},"fee_source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Fee Source"},"tax_deferred_cents":{"type":"integer","title":"Tax Deferred Cents","default":0},"tax_liability":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tax Liability"},"tax_basis":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tax Basis"},"commission_reversed_cents":{"type":"integer","title":"Commission Reversed Cents","default":0},"commission_basis":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Commission Basis"},"opened_at":{"type":"string","format":"date-time","title":"Opened At"},"resolved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Resolved At"},"shares":{"items":{"$ref":"#/components/schemas/DisputeShareOut"},"type":"array","title":"Shares","default":[]}},"type":"object","required":["id","payment_id","provider_dispute_id","amount_cents","currency","reason","status","evidence_due_at","liability","liability_basis","liability_decided_by","liability_decided_at","liability_settled_at","opened_at","resolved_at"],"title":"DisputeOut","description":"A chargeback, and who bears it.\n\n`liability` is NULL while the dispute is open, and that is no longer \"nobody\nhas ruled\" — it is \"it has not been lost yet\". An open dispute may still be\nwon, in which case no money was taken and nobody bears anything."},"DisputeRowOut":{"properties":{"id":{"type":"string","title":"Id"},"payment_id":{"type":"string","title":"Payment Id"},"amount_cents":{"type":"integer","title":"Amount Cents"},"currency":{"type":"string","title":"Currency"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"status":{"type":"string","title":"Status"},"evidence_due_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Evidence Due At"},"customer_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Name"},"service_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Name"},"appointment_reference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Appointment Reference"}},"type":"object","required":["id","payment_id","amount_cents","currency","reason","status","evidence_due_at"],"title":"DisputeRowOut"},"DisputeShareOut":{"properties":{"account":{"type":"string","title":"Account"},"beneficiary_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Beneficiary Id"},"received_cents":{"type":"integer","title":"Received Cents"},"share_bps":{"type":"integer","title":"Share Bps"},"liable_cents":{"type":"integer","title":"Liable Cents"},"fee_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Fee Cents"}},"type":"object","required":["account","beneficiary_id","received_cents","share_bps","liable_cents"],"title":"DisputeShareOut","description":"One party's part of one chargeback, with the evidence for the share."},"DistinguishedBusinessesOut":{"properties":{"basis":{"type":"string","const":"verified_top_rated","title":"Basis"},"is_paid_tier":{"type":"boolean","title":"Is Paid Tier","default":false},"min_rating":{"type":"number","title":"Min Rating"},"min_reviews":{"type":"integer","title":"Min Reviews"},"items":{"items":{"$ref":"#/components/schemas/BusinessSearchOut"},"type":"array","title":"Items","default":[]}},"type":"object","required":["basis","min_rating","min_reviews"],"title":"DistinguishedBusinessesOut","description":"The rail the client's screen titles \"Platinum members\".\n\nTHERE IS NO BUSINESS TIER IN THIS PLATFORM, and this response says so out loud\nrather than letting a name imply one. `plans` and `subscriptions` are CLIENT\nmemberships — Premium and Elite, the thing a person buys for 20% off and a\ncheaper booking fee. A paid tier FOR BUSINESSES would carry a price, a\ncontract, a commission consequence and a refund policy, none of which the\nclient has specified, and none of which may be invented inside a query.\n\nSo the rail is ranked on the only standing the platform actually records:\n\n    basis         'verified_top_rated' — MyLook has verified the business, and\n                  its rating clears `min_rating` over at least `min_reviews`\n                  reviews. Verification is granted, never sold.\n    is_paid_tier  false. Stated on every response so no screen, and nobody\n                  reading this API later, can mistake merit for a purchase.\n\n`items` are the same cards `GET /businesses` returns, by design — the client's\nrow uses the very same card component, and a second, subtly different business\ncontract is how two rails start disagreeing about the same shop."},"DomainHealthOut":{"properties":{"domain":{"type":"string","title":"Domain"},"label":{"type":"string","title":"Label"},"articles":{"type":"integer","title":"Articles"},"published":{"type":"integer","title":"Published"},"pending_review":{"type":"integer","title":"Pending Review"},"outdated":{"type":"integer","title":"Outdated"},"health":{"type":"string","title":"Health"}},"type":"object","required":["domain","label","articles","published","pending_review","outdated","health"],"title":"DomainHealthOut"},"DraftIn":{"properties":{"step":{"type":"string","maxLength":7,"minLength":7,"pattern":"^ONB-0(0[1-9]|1[0-5])$","title":"Step"},"payload":{"additionalProperties":true,"type":"object","title":"Payload"}},"type":"object","required":["step"],"title":"DraftIn","description":"Auto-save, sent on every step change rather than on a timer."},"DraftOut":{"properties":{"kind":{"type":"string","title":"Kind"},"id":{"type":"string","title":"Id"},"title":{"type":"string","title":"Title"},"subtitle":{"type":"string","title":"Subtitle"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"href":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Href"}},"type":"object","required":["kind","id","title","subtitle","updated_at","href"],"title":"DraftOut"},"EarningsLineOut":{"properties":{"kind":{"type":"string","title":"Kind"},"amount_cents":{"type":"integer","title":"Amount Cents"},"count":{"type":"integer","title":"Count"}},"type":"object","required":["kind","amount_cents","count"],"title":"EarningsLineOut"},"EarningsOut":{"properties":{"scope":{"type":"string","title":"Scope"},"date_from":{"type":"string","format":"date","title":"Date From"},"date_to":{"type":"string","format":"date","title":"Date To"},"timezone":{"type":"string","title":"Timezone"},"total_cents":{"type":"integer","title":"Total Cents"},"lines":{"items":{"$ref":"#/components/schemas/EarningsLineOut"},"type":"array","title":"Lines"},"withheld_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Withheld Note"}},"type":"object","required":["scope","date_from","date_to","timezone","total_cents","lines"],"title":"EarningsOut","description":"Summed from the ledger, never recalculated from a price and a percentage.\nThe ledger is what happened; a report that disagrees with it is wrong."},"EscalateIn":{"properties":{"reason":{"type":"string","maxLength":1000,"minLength":3,"title":"Reason"}},"type":"object","required":["reason"],"title":"EscalateIn"},"EscalationDoneOut":{"properties":{"to_role":{"type":"string","title":"To Role"},"event":{"$ref":"#/components/schemas/VerificationEventOut"}},"type":"object","required":["to_role","event"],"title":"EscalationDoneOut"},"EscalationOut":{"properties":{"to_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Role"},"at":{"type":"string","format":"date-time","title":"At"},"by_role":{"type":"string","title":"By Role"}},"type":"object","required":["to_role","at","by_role"],"title":"EscalationOut"},"EscalationRoleIn":{"properties":{"role":{"type":"string","title":"Role"}},"type":"object","required":["role"],"title":"EscalationRoleIn"},"EscalationRoleOut":{"properties":{"role":{"type":"string","title":"Role"},"roles":{"items":{"type":"string"},"type":"array","title":"Roles"}},"type":"object","required":["role","roles"],"title":"EscalationRoleOut"},"ExampleProductOut":{"properties":{"name":{"type":"string","title":"Name"},"price_cents":{"type":"integer","title":"Price Cents"},"from_count":{"type":"integer","title":"From Count"}},"type":"object","required":["name","price_cents","from_count"],"title":"ExampleProductOut"},"ExampleServiceOut":{"properties":{"name":{"type":"string","title":"Name"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"price_cents":{"type":"integer","title":"Price Cents"},"from_count":{"type":"integer","title":"From Count"}},"type":"object","required":["name","duration_minutes","price_cents","from_count"],"title":"ExampleServiceOut","description":"One line of the preview menu. NOT this shop's price — see ListingPreviewOut."},"FavoriteIn":{"properties":{"kind":{"$ref":"#/components/schemas/FavoriteKind"},"target_id":{"type":"string","format":"uuid","title":"Target Id"}},"type":"object","required":["kind","target_id"],"title":"FavoriteIn"},"FavoriteKind":{"type":"string","enum":["business","professional","service","product"],"title":"FavoriteKind"},"FavoriteOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"kind":{"$ref":"#/components/schemas/FavoriteKind"},"target_id":{"type":"string","format":"uuid","title":"Target Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","user_id","kind","target_id","created_at"],"title":"FavoriteOut"},"FinanceHealthOut":{"properties":{"label":{"type":"string","title":"Label"},"all_ok":{"type":"boolean","title":"All Ok"},"items_need_review":{"type":"integer","title":"Items Need Review"}},"type":"object","required":["label","all_ok","items_need_review"],"title":"FinanceHealthOut"},"FinanceOverviewOut":{"properties":{"health":{"$ref":"#/components/schemas/FinanceHealthOut"},"failed_payouts":{"items":{"$ref":"#/components/schemas/PayoutRowOut"},"type":"array","title":"Failed Payouts"},"pending_transfers":{"items":{"$ref":"#/components/schemas/PayoutRowOut"},"type":"array","title":"Pending Transfers"},"refund_requests":{"$ref":"#/components/schemas/RefundRequestsOut"},"billing_exceptions":{"items":{"$ref":"#/components/schemas/BillingExceptionOut"},"type":"array","title":"Billing Exceptions"},"counts":{"additionalProperties":{"type":"integer"},"type":"object","title":"Counts"},"generated_at":{"type":"string","format":"date-time","title":"Generated At"}},"type":"object","required":["health","failed_payouts","pending_transfers","refund_requests","billing_exceptions","counts","generated_at"],"title":"FinanceOverviewOut"},"FollowClickIn":{"properties":{"network":{"type":"string","maxLength":20,"title":"Network"},"source":{"type":"string","maxLength":20,"title":"Source","default":"registration"}},"type":"object","required":["network"],"title":"FollowClickIn","description":"HIS SCREEN 6 / 11 - instagram, tiktok, facebook or youtube."},"FollowClickOut":{"properties":{"network":{"type":"string","title":"Network"},"source":{"type":"string","title":"Source"},"clicked_at":{"type":"string","format":"date-time","title":"Clicked At"}},"type":"object","required":["network","source","clicked_at"],"title":"FollowClickOut"},"ForgotPasswordIn":{"properties":{"email":{"type":"string","format":"email","title":"Email"}},"type":"object","required":["email"],"title":"ForgotPasswordIn"},"FraudAlertIn":{"properties":{"summary":{"type":"string","maxLength":2000,"minLength":3,"title":"Summary"},"severity":{"type":"string","enum":["low","medium","high"],"title":"Severity","default":"medium"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"evidence":{"additionalProperties":true,"type":"object","title":"Evidence"}},"type":"object","required":["summary"],"title":"FraudAlertIn"},"FraudAlertOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"kind":{"type":"string","title":"Kind"},"severity":{"type":"string","title":"Severity"},"status":{"type":"string","title":"Status"},"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"summary":{"type":"string","title":"Summary"},"evidence":{"additionalProperties":true,"type":"object","title":"Evidence","default":{}},"raised_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Raised By"},"resolved_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Resolved By"},"resolved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Resolved At"},"resolution":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","kind","severity","status","summary","created_at"],"title":"FraudAlertOut"},"HTTPValidationError":{"properties":{"detail":{"items":{"$ref":"#/components/schemas/ValidationError"},"type":"array","title":"Detail"}},"type":"object","title":"HTTPValidationError"},"HeldPenaltiesOut":{"properties":{"total_cents":{"type":"integer","title":"Total Cents"},"entries":{"items":{"$ref":"#/components/schemas/HeldPenaltyOut"},"type":"array","title":"Entries"},"decision":{"type":"string","title":"Decision"}},"type":"object","required":["total_cents","entries","decision"],"title":"HeldPenaltiesOut","description":"What is left in penalty_holding — which should be nothing.\n\nThe 2026-08-11 freeze set a 30% penalty for a late cancellation and for a\nno-show and never said who receives it, so it was held rather than given to\nanybody. The owner ruled on 2026-08-12 that it belongs to the affected\nprofessional; migration 031 released the balance and refunds credit them\ndirectly. The screen stays because a total above zero now means something\nspecific and worth chasing: a penalty on a payment that names no\nprofessional, which his decision does not reach."},"HeldPenaltyOut":{"properties":{"payment_id":{"type":"string","title":"Payment Id"},"appointment_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Appointment Id"},"amount_cents":{"type":"integer","title":"Amount Cents"},"held_since":{"type":"string","title":"Held Since"},"description":{"type":"string","title":"Description"}},"type":"object","required":["payment_id","appointment_id","amount_cents","held_since","description"],"title":"HeldPenaltyOut","description":"A cancellation penalty still credited to nobody, and where it came from."},"HourOverrideIn":{"properties":{"is_closed":{"type":"boolean","title":"Is Closed","default":true},"opens_at":{"anyOf":[{"type":"string","format":"time"},{"type":"null"}],"title":"Opens At"},"closes_at":{"anyOf":[{"type":"string","format":"time"},{"type":"null"}],"title":"Closes At"},"reason":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Reason"}},"type":"object","title":"HourOverrideIn","description":"One date's exception (adjustment 11, Scheduling MVP): closed, or open with\nthese hours instead of the weekday's."},"HourOverrideOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"on_date":{"type":"string","format":"date","title":"On Date"},"is_closed":{"type":"boolean","title":"Is Closed"},"opens_at":{"anyOf":[{"type":"string","format":"time"},{"type":"null"}],"title":"Opens At"},"closes_at":{"anyOf":[{"type":"string","format":"time"},{"type":"null"}],"title":"Closes At"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","required":["id","branch_id","on_date","is_closed","opens_at","closes_at","reason"],"title":"HourOverrideOut"},"HubOut":{"properties":{"continue_working":{"anyOf":[{"additionalProperties":true,"type":"object"},{"type":"null"}],"title":"Continue Working"},"priority_queue":{"items":{"$ref":"#/components/schemas/QueueItemOut"},"type":"array","title":"Priority Queue"},"assigned_cases":{"items":{"$ref":"#/components/schemas/AssignedCaseOut"},"type":"array","title":"Assigned Cases"},"pending_approvals":{"items":{"$ref":"#/components/schemas/ApprovalOut"},"type":"array","title":"Pending Approvals"},"draft_operations":{"items":{"$ref":"#/components/schemas/DraftOut"},"type":"array","title":"Draft Operations"},"counts":{"additionalProperties":{"type":"integer"},"type":"object","title":"Counts"}},"type":"object","required":["continue_working","priority_queue","assigned_cases","pending_approvals","draft_operations","counts"],"title":"HubOut"},"IngestBatchIn":{"properties":{"listings":{"items":{"$ref":"#/components/schemas/ListingIngestIn"},"type":"array","maxItems":1000,"minItems":1,"title":"Listings"}},"type":"object","required":["listings"],"title":"IngestBatchIn"},"IngestResultOut":{"properties":{"received":{"type":"integer","title":"Received"},"deduplicated":{"type":"integer","title":"Deduplicated"},"inserted":{"type":"integer","title":"Inserted"},"updated":{"type":"integer","title":"Updated"},"skipped_claimed":{"type":"integer","title":"Skipped Claimed"},"unknown_categories":{"type":"integer","title":"Unknown Categories"},"uncategorised":{"type":"integer","title":"Uncategorised","default":0}},"type":"object","required":["received","deduplicated","inserted","updated","skipped_claimed","unknown_categories"],"title":"IngestResultOut","description":"Deliberately explicit: a second run of the same batch reports the same\n`received` with 0 inserted, which is how idempotency is observed."},"InstantPayoutOut":{"properties":{"eligible":{"type":"boolean","title":"Eligible"},"available_cents":{"type":"integer","title":"Available Cents"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","required":["eligible","available_cents"],"title":"InstantPayoutOut","description":"HIS §29: the screen shows this block only when `eligible` AND a balance."},"IntegrationOut":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"purpose":{"type":"string","title":"Purpose"},"status":{"type":"string","title":"Status"},"detail":{"type":"string","title":"Detail"}},"type":"object","required":["key","label","purpose","status","detail"],"title":"IntegrationOut"},"InventoryAdjustmentIn":{"properties":{"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"variant_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Variant Id"},"delta":{"type":"integer","maximum":100000.0,"minimum":-100000.0,"title":"Delta"},"reason":{"type":"string","maxLength":200,"minLength":3,"title":"Reason"},"client_request_id":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Client Request Id"}},"type":"object","required":["delta","reason"],"title":"InventoryAdjustmentIn","description":"STD-002 Inventory Adjustment — Product ID (the path), Quantity, Adjustment\nReason. `delta` is the movement (+ restock, − correction); VAL-009 makes the\nreason mandatory; `client_request_id` is FQA-064's idempotency key."},"InventoryAdjustmentOut":{"properties":{"variant_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Variant Id"},"id":{"type":"string","format":"uuid","title":"Id"},"product_id":{"type":"string","format":"uuid","title":"Product Id"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"delta":{"type":"integer","title":"Delta"},"previous_quantity":{"type":"integer","title":"Previous Quantity"},"new_quantity":{"type":"integer","title":"New Quantity"},"reason":{"type":"string","title":"Reason"},"performed_by":{"type":"string","format":"uuid","title":"Performed By"},"performed_role":{"type":"string","title":"Performed Role"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"replayed":{"type":"boolean","title":"Replayed","default":false}},"type":"object","required":["id","product_id","branch_id","delta","previous_quantity","new_quantity","reason","performed_by","performed_role","created_at"],"title":"InventoryAdjustmentOut"},"InventoryLevelOut":{"properties":{"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"branch_name":{"type":"string","title":"Branch Name"},"variant_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Variant Id"},"variant_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Variant Label"},"quantity":{"type":"integer","title":"Quantity"},"low_stock_threshold":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Low Stock Threshold"},"state":{"type":"string","enum":["in_stock","low_stock","out_of_stock"],"title":"State"},"configured_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Configured At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["branch_id","branch_name","quantity","state"],"title":"InventoryLevelOut","description":"Stock at ONE location — STD-002 `inventory`.\n\nA level only exists where a row does. A location with no row does not appear\nhere at all; it appears in `unconfigured_branches` on the product, because\n\"nobody has counted at the Brickell shop\" is a fact about that shop, not a\nquantity."},"InventoryThresholdIn":{"properties":{"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"variant_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Variant Id"},"low_stock_threshold":{"anyOf":[{"type":"integer","maximum":100000.0,"minimum":0.0},{"type":"null"}],"title":"Low Stock Threshold"}},"type":"object","title":"InventoryThresholdIn"},"JourneyOut":{"properties":{"roles":{"items":{"type":"string","enum":["client","professional","business"]},"type":"array","title":"Roles"},"steps":{"items":{"type":"string"},"type":"array","title":"Steps"},"total":{"type":"integer","title":"Total"},"step":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Step"},"payload":{"additionalProperties":true,"type":"object","title":"Payload"},"completed":{"type":"boolean","title":"Completed","default":false}},"type":"object","required":["roles","steps","total"],"title":"JourneyOut","description":"What this person's onboarding actually looks like.\n\n`steps` is the whole journey and `total` is the N in his \"Step n of N\" —\nwhich is why it is computed here and never hard-coded in the app: \"No\nutilizar un número fijo porque cada ruta tiene diferente longitud.\""},"LanguageIn":{"properties":{"code":{"type":"string","maxLength":8,"minLength":2,"pattern":"^[a-z][a-z0-9-]*$","title":"Code"},"name":{"type":"string","maxLength":60,"minLength":2,"title":"Name"},"aliases":{"items":{"type":"string"},"type":"array","title":"Aliases","default":[]},"sort_order":{"type":"integer","title":"Sort Order","default":100},"reason":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Reason"}},"type":"object","required":["code","name"],"title":"LanguageIn","description":"Extend the canonical taxonomy — his \"ampliar correctamente\"."},"LanguageUpdateIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":60,"minLength":2},{"type":"null"}],"title":"Name"},"aliases":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Aliases"},"sort_order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Sort Order"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"},"reason":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Reason"}},"type":"object","title":"LanguageUpdateIn","description":"Correct an entry, or retire it.\n\nADDING WITHOUT THIS WOULD BE A ONE-WAY DOOR — a typo in a language code, or\nan entry added in good faith that turns out to be a dialect of one already\nlisted, would be permanent and public. Retiring is `is_active = false`, never\na delete: professionals and businesses may already have chosen it, and\ndeleting the row would take their answer away without asking them. The same\nrule as everything else here — the value stops being offered, not existing."},"LegacyResolveIn":{"properties":{"resolution":{"type":"string","pattern":"^(mapped|needs_taxonomy|ambiguous|rejected)$","title":"Resolution"},"language_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Language Code"},"note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Note"}},"type":"object","required":["resolution"],"title":"LegacyResolveIn","description":"A person's decision about one value.\n\n`mapped` REQUIRES `language_code`. MyLook will not work out which language\nsomething is: \"NO SILENT MAPPING\" means the mapping comes from a person or\nit does not happen."},"LegacyValueOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"raw_value":{"type":"string","title":"Raw Value"},"normalized_value":{"type":"string","title":"Normalized Value"},"status":{"type":"string","title":"Status"},"language_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Language Id"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"reviewed_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Reviewed By"}},"type":"object","required":["id","business_id","raw_value","normalized_value","status"],"title":"LegacyValueOut"},"ListingDetailOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"source":{"type":"string","title":"Source"},"source_ref":{"type":"string","title":"Source Ref"},"name":{"type":"string","title":"Name"},"category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Category Id"},"source_category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Category"},"street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code"},"country":{"type":"string","title":"Country"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"},"instagram":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instagram"},"status":{"type":"string","title":"Status"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"harvested_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Harvested At"},"claimable":{"type":"boolean","title":"Claimable"},"preview":{"anyOf":[{"$ref":"#/components/schemas/ListingPreviewOut"},{"type":"null"}]}},"type":"object","required":["id","source","source_ref","name","category_id","source_category","street","city","state","postal_code","country","latitude","longitude","phone","website","instagram","status","business_id","harvested_at","claimable"],"title":"ListingDetailOut","description":"`claimable` saves every client from re-deriving the rule from `status`."},"ListingIngestIn":{"properties":{"source":{"type":"string","maxLength":40,"minLength":1,"title":"Source","default":"osm"},"source_ref":{"type":"string","maxLength":200,"minLength":1,"title":"Source Ref"},"name":{"type":"string","maxLength":200,"minLength":1,"title":"Name"},"category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Category Id"},"source_category":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Source Category"},"street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code"},"country":{"type":"string","maxLength":2,"minLength":2,"title":"Country","default":"US"},"latitude":{"anyOf":[{"type":"number","maximum":90.0,"minimum":-90.0},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number","maximum":180.0,"minimum":-180.0},{"type":"null"}],"title":"Longitude"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"},"instagram":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instagram"},"harvested_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Harvested At"}},"type":"object","required":["source_ref","name"],"title":"ListingIngestIn","description":"One harvested place. (source, source_ref) is its identity at the origin,\nwhich is what makes re-running an import an update instead of a duplicate."},"ListingPreviewOut":{"properties":{"is_example":{"type":"boolean","title":"Is Example","default":true},"category_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Slug"},"category_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Name"},"services":{"items":{"$ref":"#/components/schemas/ExampleServiceOut"},"type":"array","title":"Services","default":[]},"products":{"items":{"$ref":"#/components/schemas/ExampleProductOut"},"type":"array","title":"Products","default":[]}},"type":"object","title":"ListingPreviewOut","description":"What this shop's MyLook page WOULD look like — not what it charges.\n\n`is_example` is set by the server and is always true. It travels in the\npayload rather than being left to each screen, because the distinction is\nthe difference between a recruiting preview and publishing invented prices\nunder a real business's name. An app that forgets to read a flag it was\nnever sent has an excuse; this leaves none.\n\nEvery figure is the median across REAL MyLook businesses in the same\ncategory. Nothing is invented, and a category with no real services behind\nit returns empty lists rather than something made up."},"ListingSearchOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"source":{"type":"string","title":"Source"},"source_ref":{"type":"string","title":"Source Ref"},"name":{"type":"string","title":"Name"},"category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Category Id"},"source_category":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source Category"},"street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code"},"country":{"type":"string","title":"Country"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"},"instagram":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instagram"},"status":{"type":"string","title":"Status"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"harvested_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Harvested At"},"distance_miles":{"type":"number","title":"Distance Miles"}},"type":"object","required":["id","source","source_ref","name","category_id","source_category","street","city","state","postal_code","country","latitude","longitude","phone","website","instagram","status","business_id","harvested_at","distance_miles"],"title":"ListingSearchOut"},"LocationCapacityEventOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"actor_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Actor Id"},"actor_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actor Role"},"before_state":{"additionalProperties":true,"type":"object","title":"Before State","default":{}},"after_state":{"additionalProperties":true,"type":"object","title":"After State","default":{}},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","branch_id","created_at"],"title":"LocationCapacityEventOut","description":"HIS REFINEMENT 08 — one recorded change to what a location can DO.\n\nPublication is not in here on purpose: `is_active` answers a different\nquestion and mixing the two would make this log unreadable exactly when\nsomebody needs it."},"LocationClosureActionOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"operational_status":{"type":"string","title":"Operational Status"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"appointment_count":{"type":"integer","title":"Appointment Count"},"effective_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Effective At"},"status":{"type":"string","title":"Status"},"resolution":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution"},"resolution_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Resolution Note"},"resolved_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Resolved At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"options":{"items":{"type":"string"},"type":"array","title":"Options","default":[]}},"type":"object","required":["id","branch_id","business_id","operational_status","appointment_count","status","created_at"],"title":"LocationClosureActionOut","description":"HIS DECISION 145 — a closing location's stranded appointments, as a\npiece of work somebody has to decide about.\n\n`appointment_count` is a snapshot taken when the location stopped taking\nbookings, not a live count: it is the number the owner was asked about."},"LocationClosureResolveIn":{"properties":{"resolution":{"type":"string","title":"Resolution"},"note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Note"}},"type":"object","required":["resolution"],"title":"LocationClosureResolveIn","description":"Keep · move to another location · move to another professional and\nlocation · reschedule · cancel with client notification.\n\nChoosing here RECORDS the decision. Carrying it out is a reschedule or a\ncancellation, made by a person through the routes that already exist and\nalready tell the client — \"MyLook puede recomendar, pero nunca cambiar la\ndireccion de una cita sin consentimiento\"."},"LoginIn":{"properties":{"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Phone"},"password":{"type":"string","title":"Password"},"device_label":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Device Label"}},"type":"object","required":["password"],"title":"LoginIn","description":"HIS \"Sign in with your phone number to continue\" — the Account Exists state of both flows.\n\nAn e-mail OR a phone number, whichever the account was made with."},"MatchedServiceOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"price_cents":{"type":"integer","title":"Price Cents"},"duration_minutes":{"type":"integer","title":"Duration Minutes"}},"type":"object","required":["id","name","price_cents","duration_minutes"],"title":"MatchedServiceOut","description":"HIS DECISION 72 — the service a search was measured on: the cheapest\nactive service of the business matching the `service` filter."},"MeUpdateIn":{"properties":{"full_name":{"anyOf":[{"type":"string","maxLength":120,"minLength":2},{"type":"null"}],"title":"Full Name"},"phone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Phone"},"locale":{"anyOf":[{"type":"string","pattern":"^(en|es)$"},{"type":"null"}],"title":"Locale"},"avatar_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Key"},"username":{"anyOf":[{"type":"string","maxLength":30,"minLength":3,"pattern":"^[a-z0-9][a-z0-9-]*$"},{"type":"null"}],"title":"Username"},"date_of_birth":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date Of Birth"},"city":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"City"},"personalized_recommendations":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Personalized Recommendations"}},"type":"object","title":"MeUpdateIn","description":"What a person may change about themselves.\n\nOnly fields they own. EMAIL IS ABSENT and deliberately so: changing it is a\nverification flow, not an edit — allowing it here would let somebody point\nan account at an address they have not proved they can read, which is the\nwhole of an account takeover.\n\n`status`, `email_verified_at` and the rest are the platform's, and a person\nwho could set their own would be granting themselves standing. Same rule as\nthe business tick.\n\nOmitting a field leaves it alone; sending null clears it. So setting a\nphotograph does not erase a phone number."},"MediaConsentIn":{"properties":{"granted":{"type":"boolean","title":"Granted"}},"type":"object","required":["granted"],"title":"MediaConsentIn","description":"Grant or revoke — his pantalla draws both, and the second one matters."},"MediaOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"key":{"type":"string","title":"Key"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"},"kind":{"type":"string","title":"Kind"},"content_type":{"type":"string","title":"Content Type"},"byte_size":{"type":"integer","title":"Byte Size"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","key","url","kind","content_type","byte_size","created_at"],"title":"MediaOut","description":"What the app gets back. `key` is what you store on the entity; `url` is\nwhat you render — it changes with the deployment, the key does not."},"MemberActionIn":{"properties":{"reason":{"anyOf":[{"type":"string","maxLength":500,"minLength":3},{"type":"null"}],"title":"Reason","description":"Why. Kept forever, against the person who made the change."}},"type":"object","title":"MemberActionIn","description":"The body of suspend / reactivate / revoke, and of DELETE on a member.\n\nHIS ANSWER TO QUESTION 179 (2026-09-14): the reason is REQUIRED when the move\naffects another person — members.py refuses one without it (`reason_required`).\nOn one's own membership it may be left out, and the move is recorded as\nSELF_PERMISSION_REDUCTION."},"MemberEventOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"member_id":{"type":"string","format":"uuid","title":"Member Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"action":{"type":"string","title":"Action"},"actor_id":{"type":"string","format":"uuid","title":"Actor Id"},"actor_role":{"type":"string","title":"Actor Role"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"before_state":{"additionalProperties":true,"type":"object","title":"Before State"},"after_state":{"additionalProperties":true,"type":"object","title":"After State"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","member_id","business_id","action","actor_id","actor_role","reason","before_state","after_state","created_at"],"title":"MemberEventOut","description":"One administrative change, as it was recorded. Append-only: no route\nedits or removes one, which is the only reason the history is worth\nreading."},"MemberOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"role":{"type":"string","title":"Role"},"permissions":{"additionalProperties":true,"type":"object","title":"Permissions"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"full_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Full Name"},"avatar_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Key"},"invited_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Invited By"},"accepted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Accepted At"},"consent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Consent"},"invitation_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Invitation Id"},"professional_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Professional Id"},"suspended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Suspended At"},"suspended_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Suspended By"},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Revoked At"},"revoked_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Revoked By"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"}},"type":"object","required":["id","user_id","business_id","branch_id","role","permissions","created_at"],"title":"MemberOut","description":"One person's access, with the whole of its current state.\n\nThe lifecycle fields are here because a team screen that cannot tell an\nactive barber from a suspended one, or say who ended somebody's access and\nwhen, is the screen the client's audit was about."},"MemberUpdateIn":{"properties":{"role":{"anyOf":[{"type":"string","pattern":"^(owner|manager|professional|front_desk|assistant)$"},{"type":"null"}],"title":"Role"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"permissions":{"anyOf":[{"additionalProperties":{"type":"boolean"},"type":"object"},{"type":"null"}],"title":"Permissions"},"reason":{"anyOf":[{"type":"string","maxLength":500,"minLength":3},{"type":"null"}],"title":"Reason"}},"type":"object","title":"MemberUpdateIn","description":"Everything about one person's access that can change while they work here.\n\nEvery field is optional, and OMITTING one means \"leave it alone\" — the same\ncontract `BusinessUpdateIn` keeps. It matters more here: `branch_id: null`\nis a MEANINGFUL value that means \"covers the whole business\", so a form that\nsent the field it did not edit would promote people by accident.\n\nEnding the relationship is NOT here. Revocation is its own endpoint because\nit is not an edit — it is the end of the record, and it deserves a route a\nreviewer can find rather than a magic value in a PATCH."},"MembershipMemberOut":{"properties":{"subscription_id":{"type":"string","format":"uuid","title":"Subscription Id"},"client_user_id":{"type":"string","format":"uuid","title":"Client User Id"},"client_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Name"},"avatar_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Key"},"status":{"type":"string","title":"Status"},"current_period_start":{"type":"string","format":"date-time","title":"Current Period Start"},"current_period_end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Current Period End"},"cancelled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Cancelled At"},"in_force":{"type":"boolean","title":"In Force"}},"type":"object","required":["subscription_id","client_user_id","status","current_period_start","current_period_end","cancelled_at","in_force"],"title":"MembershipMemberOut","description":"One member of a shop's plan, as the OWNER reads the roster — his\n\"153 Members · View Members\". The subscription with the person behind it;\n`in_force` answers the question the shop actually has at the door."},"MembershipStateOut":{"properties":{"is_member":{"type":"boolean","title":"Is Member"},"booking_fee_cents":{"type":"integer","title":"Booking Fee Cents"},"service_discount_bps":{"type":"integer","title":"Service Discount Bps"},"subscription":{"anyOf":[{"$ref":"#/components/schemas/SubscriptionOut"},{"type":"null"}]}},"type":"object","required":["is_member","booking_fee_cents","service_discount_bps"],"title":"MembershipStateOut","description":"What the app needs to render the Memberships section for a signed-in person,\nresolved on the server so the fee shown is the fee charged.\n\n`is_member` is about the MYLOOK-WIDE membership only. A client who holds three\nbusinesses' own memberships is still `is_member: false` here and still pays the\nUS$2.99 fee — those are the businesses' products, listed at\nGET /v1/me/memberships. Decision freeze v1.0 §3B/§3C."},"ModerateIn":{"properties":{"action":{"type":"string","enum":["removed","restored","kept"],"title":"Action"},"public_reason":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Public Reason"},"internal_note":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Internal Note"}},"type":"object","required":["action"],"title":"ModerateIn","description":"A moderator's decision.\n\n`public_reason` is the GENERAL category the business may be told — his\ndecision 36 — and `internal_note` never leaves MyLook."},"ModerationQueueItemOut":{"properties":{"review_id":{"type":"string","format":"uuid","title":"Review Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"rating":{"type":"integer","title":"Rating"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment"},"state":{"type":"string","title":"State"},"reporters":{"type":"integer","title":"Reporters"},"reasons":{"items":{"type":"string"},"type":"array","title":"Reasons"},"first_reported_at":{"type":"string","format":"date-time","title":"First Reported At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["review_id","business_id","rating","comment","state","reporters","reasons","first_reported_at","created_at"],"title":"ModerationQueueItemOut","description":"One review a moderator has to decide about — his decision 17."},"MoneySettingOut":{"properties":{"id":{"type":"string","title":"Id"},"key":{"type":"string","title":"Key"},"value_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Value Cents"},"value_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Value Bps"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"effective_from":{"type":"string","format":"date-time","title":"Effective From"},"effective_to":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Effective To"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"}},"type":"object","required":["id","key","value_cents","value_bps","country","state","effective_from","effective_to","note"],"title":"MoneySettingOut"},"MoveProposalOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"appointment_id":{"type":"string","format":"uuid","title":"Appointment Id"},"from_starts_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"From Starts At"},"to_starts_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"To Starts At"},"proposed_by":{"type":"string","format":"uuid","title":"Proposed By"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"status":{"type":"string","enum":["pending","accepted","declined","withdrawn","lapsed"],"title":"Status"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"decided_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Decided At"}},"type":"object","required":["id","appointment_id","from_starts_at","to_starts_at","proposed_by","reason","status","created_at","decided_at"],"title":"MoveProposalOut","description":"HIS DECISION 79 — the shop's request to move a booking, as both sides read\nit. `from_starts_at` is where the booking IS (nothing changed when this was\nwritten); `to_starts_at` is where the shop asks it to go. Defined above\nAppointmentOut, which carries it: a forward reference to a class defined\nlater fails at request time, not at import."},"MoveProposeIn":{"properties":{"starts_at":{"type":"string","format":"date-time","title":"Starts At"},"reason":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Reason"}},"type":"object","required":["starts_at"],"title":"MoveProposeIn","description":"Where the shop wants the booking to go. A time and a reason, nothing else\n— the same discipline as RescheduleIn: professional, service, price and\nlocation are not on a move. 300 characters is the note length the status\nchange already allows."},"MyAccessOut":{"properties":{"business_id":{"type":"string","format":"uuid","title":"Business Id"},"role":{"type":"string","title":"Role"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"capabilities":{"items":{"type":"string"},"type":"array","title":"Capabilities"},"memberships":{"items":{"$ref":"#/components/schemas/AccessMembershipOut"},"type":"array","title":"Memberships"}},"type":"object","required":["business_id","role","branch_id","capabilities","memberships"],"title":"MyAccessOut","description":"What the caller may do here — the apps use this to render, but the server\nenforces it regardless of what the app decides to show.\n\n`memberships` is the answer: every membership the caller holds here, each with its location, its state and its\nown capabilities. A screen decides by what holds where it acts — his words: \"The app should consume role + scope\n+ state + capabilities and decide UI actions by effective capability/scope rather than role name alone.\"\n`role`, `branch_id` and `capabilities` stay for apps built before it, and describe ONE active membership: the\nwhole business's when there is one, otherwise the oldest."},"MyAppointmentOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"reference":{"type":"string","title":"Reference"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"professional_id":{"type":"string","format":"uuid","title":"Professional Id"},"client_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Client User Id"},"service_id":{"type":"string","format":"uuid","title":"Service Id"},"agreement_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Agreement Id"},"starts_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Starts At"},"ends_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ends At"},"guest_phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Guest Phone"},"payment_channel":{"type":"string","title":"Payment Channel","default":"mylook"},"created_by_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By User Id"},"service_name_snapshot":{"type":"string","title":"Service Name Snapshot"},"duration_minutes_snapshot":{"type":"integer","title":"Duration Minutes Snapshot"},"price_cents_snapshot":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price Cents Snapshot"},"options_snapshot":{"items":{},"type":"array","title":"Options Snapshot"},"status":{"type":"string","enum":["pending_payment","confirmed","checked_in","in_progress","completed","cancelled_client","cancelled_business","no_show"],"title":"Status"},"client_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Note"},"reference_image_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reference Image Key"},"booked_for_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Booked For Name"},"source":{"type":"string","title":"Source"},"cancelled_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancelled At"},"cancellation_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancellation Reason"},"completed_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Completed At"},"created_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Created At"},"pending_move":{"anyOf":[{"$ref":"#/components/schemas/MoveProposalOut"},{"type":"null"}]},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"business_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Name"},"business_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Slug"},"cover_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Key"},"branch_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch Name"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"professional_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Professional Name"},"professional_avatar_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Professional Avatar Key"},"utc_offset_minutes":{"type":"integer","title":"Utc Offset Minutes","default":0},"payment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Payment Id"},"paid_total_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Paid Total Cents"},"refunded_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Refunded Cents"},"card_brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Card Brand"},"card_last4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Card Last4"},"paid_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Paid At"}},"type":"object","required":["id","reference","branch_id","professional_id","service_id","agreement_id","starts_at","ends_at","service_name_snapshot","duration_minutes_snapshot","price_cents_snapshot","options_snapshot","status","client_note","reference_image_key","booked_for_name","source","cancelled_at","cancellation_reason","completed_at","created_at"],"title":"MyAppointmentOut","description":"An appointment as the person who booked it reads it back.\n\nAppointmentOut carries branch_id and professional_id and nothing that\nresolves them, so the Bookings screen — whose card leads with a shop\nphotograph and the professional's name — had visibly empty places on it and\nno way to fill them without a request per row.\n\nNone of these are new facts. They are the same joins the app would otherwise\nmake twenty times, done once."},"MyBookingIn":{"properties":{"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"service_id":{"type":"string","format":"uuid","title":"Service Id"},"starts_at":{"type":"string","format":"date-time","title":"Starts At"},"client_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Client User Id"},"guest_name":{"anyOf":[{"type":"string","maxLength":120,"minLength":2},{"type":"null"}],"title":"Guest Name"},"guest_phone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Guest Phone"},"payment_channel":{"type":"string","enum":["mylook","at_the_shop"],"title":"Payment Channel","default":"at_the_shop"},"source":{"type":"string","enum":["walk_in","phone"],"title":"Source","default":"walk_in"},"client_note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Client Note"}},"type":"object","required":["branch_id","service_id","starts_at"],"title":"MyBookingIn","description":"HIS §14: a professional filling one of their own open gaps.\n\nTHE SAME SHAPE AS THE SHOP'S, MINUS THE ONE FIELD THAT COULD BE ABUSED. There is no\n`professional_id`: the column is the caller's own, so there is no field through which\nsomebody could put a client in a colleague's chair. Everything else — one client and never\ntwo, the payment channel, the walk-in or phone source — is his decision 12 unchanged."},"MyInvitationOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"business_name":{"type":"string","title":"Business Name"},"business_slug":{"type":"string","title":"Business Slug"},"business_logo_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Logo Key"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"branch_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch Name"},"branch_city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch City"},"role":{"type":"string","title":"Role"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"invited_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Invited By Name"},"status":{"type":"string","title":"Status"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"responded_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Responded At"},"new_invitation_requested_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"New Invitation Requested At"},"member_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Member Id"},"professional_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Professional Id"}},"type":"object","required":["id","business_id","business_name","business_slug","role","status","created_at","expires_at"],"title":"MyInvitationOut","description":"An invitation as the INVITED PERSON sees it — who is asking, for what, until when."},"MyProfessionsOut":{"properties":{"primary":{"anyOf":[{"$ref":"#/components/schemas/ProfessionOut"},{"type":"null"}]},"all":{"items":{"$ref":"#/components/schemas/ProfessionOut"},"type":"array","title":"All","default":[]}},"type":"object","title":"MyProfessionsOut"},"MyRelationshipOut":{"properties":{"business_id":{"type":"string","format":"uuid","title":"Business Id"},"business_name":{"type":"string","title":"Business Name"},"business_slug":{"type":"string","title":"Business Slug"},"kind":{"type":"string","title":"Kind"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"branch_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch Name"},"role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Role"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"status":{"type":"string","title":"Status"},"consent":{"type":"string","title":"Consent"},"started_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"},{"type":"null"}],"title":"Started At"},"ended_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"string","format":"date"},{"type":"null"}],"title":"Ended At"}},"type":"object","required":["business_id","business_name","business_slug","kind","status","consent"],"title":"MyRelationshipOut","description":"One of the signed-in person's relationships with a business, as they see it."},"NeedsAttentionOut":{"properties":{"date":{"type":"string","format":"date","title":"Date"},"timezone":{"type":"string","title":"Timezone"},"total":{"type":"integer","title":"Total","default":0},"items":{"items":{"$ref":"#/components/schemas/AttentionItemOut"},"type":"array","title":"Items"}},"type":"object","required":["date","timezone"],"title":"NeedsAttentionOut"},"NextServiceOut":{"properties":{"timezone":{"type":"string","title":"Timezone"},"appointment":{"anyOf":[{"$ref":"#/components/schemas/DayBookingOut"},{"type":"null"}]},"day_offset":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Day Offset"}},"type":"object","required":["timezone"],"title":"NextServiceOut"},"NotificationFamilyOut":{"properties":{"kind":{"type":"string","title":"Kind"},"label":{"type":"string","title":"Label"},"detail":{"type":"string","title":"Detail"},"email":{"type":"boolean","title":"Email","default":true}},"type":"object","required":["kind","label","detail"],"title":"NotificationFamilyOut","description":"One thing a person can be told about, and whether they want it emailed."},"NotificationKindRuleOut":{"properties":{"kind":{"type":"string","title":"Kind"},"family":{"type":"string","title":"Family"},"his_phrase":{"type":"string","title":"His Phrase"},"audience":{"type":"string","title":"Audience"},"always_on":{"type":"boolean","title":"Always On"},"user_may_switch":{"type":"boolean","title":"User May Switch"},"channels":{"additionalProperties":{"type":"string"},"type":"object","title":"Channels"}},"type":"object","required":["kind","family","his_phrase","audience","always_on","user_may_switch","channels"],"title":"NotificationKindRuleOut"},"NotificationOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"kind":{"type":"string","title":"Kind"},"title":{"type":"string","title":"Title"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"},"payload":{"additionalProperties":true,"type":"object","title":"Payload","default":{}},"read_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Read At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","user_id","kind","title","body","read_at","created_at"],"title":"NotificationOut"},"NotificationPreferencesIn":{"properties":{"email":{"additionalProperties":{"type":"boolean"},"type":"object","title":"Email"},"short_reminder":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Short Reminder"}},"type":"object","title":"NotificationPreferencesIn","description":"Only the families the person changed; anything absent is left alone."},"NotificationPreferencesOut":{"properties":{"families":{"items":{"$ref":"#/components/schemas/NotificationFamilyOut"},"type":"array","title":"Families"},"short_reminder":{"type":"boolean","title":"Short Reminder","default":true},"always_on":{"items":{"type":"string"},"type":"array","title":"Always On","default":[]}},"type":"object","required":["families"],"title":"NotificationPreferencesOut"},"NotificationRulesOut":{"properties":{"kinds":{"items":{"$ref":"#/components/schemas/NotificationKindRuleOut"},"type":"array","title":"Kinds"},"routing":{"items":{"$ref":"#/components/schemas/OperationalRouteOut"},"type":"array","title":"Routing"},"roles":{"items":{"type":"string"},"type":"array","title":"Roles"},"channels_available":{"additionalProperties":{"type":"string"},"type":"object","title":"Channels Available"},"templates":{"additionalProperties":{"type":"string"},"type":"object","title":"Templates"}},"type":"object","required":["kinds","routing","roles","channels_available","templates"],"title":"NotificationRulesOut"},"NotificationSettingsIn":{"properties":{"push_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Push Enabled"},"marketing_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Marketing Enabled"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"}},"type":"object","title":"NotificationSettingsIn","description":"HIS \"Yes, enable notifications\" or \"Not now\"."},"NotificationSettingsOut":{"properties":{"push_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Push Enabled"},"marketing_enabled":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Marketing Enabled"},"source":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Source"},"decided_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Decided At"}},"type":"object","title":"NotificationSettingsOut"},"NotifyMeIn":{"properties":{"variant_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Variant Id"}},"type":"object","title":"NotifyMeIn","description":"Which THING: the product, or one option of it. A client who wants the\n500 ml does not want to hear about the 250 ml."},"NotifyMeOut":{"properties":{"product_id":{"type":"string","format":"uuid","title":"Product Id"},"variant_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Variant Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"notified":{"type":"boolean","title":"Notified","default":false}},"type":"object","required":["product_id","created_at"],"title":"NotifyMeOut"},"OnboardingLinkOut":{"properties":{"url":{"type":"string","title":"Url"},"expires_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Expires At"}},"type":"object","required":["url","expires_at"],"title":"OnboardingLinkOut","description":"Single-use and short-lived at the processor, so the expiry travels with\nit — nothing downstream should be written assuming it lasts."},"OpenGapOut":{"properties":{"starts_at":{"title":"Starts At"},"ends_at":{"title":"Ends At"},"minutes":{"type":"integer","title":"Minutes"}},"type":"object","required":["starts_at","ends_at","minutes"],"title":"OpenGapOut","description":"Free time, COMPUTED from his §12 formula. Never stored, never typed in."},"OpeningStockIn":{"properties":{"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"quantity":{"type":"integer","maximum":1000000.0,"minimum":0.0,"title":"Quantity"},"low_stock_threshold":{"anyOf":[{"type":"integer","maximum":100000.0,"minimum":0.0},{"type":"null"}],"title":"Low Stock Threshold"}},"type":"object","required":["quantity"],"title":"OpeningStockIn","description":"How many there are at one location, on the day the product is created.\n\n    \"Stock is initialised when a product is created, PER LOCATION.\"\n                                                    — his decision 61\n\nPER LOCATION is the reason this is a list and not a number. A chain with\nthree shops does not have the same six bottles in all three, and writing one\nfigure into every location would be a lie the platform then sells against.\n\n`branch_id` may be omitted by a shop with one location, or by a member who\nbelongs to one — the same convention the stock-movement payload already uses."},"OperationalRouteOut":{"properties":{"event":{"type":"string","title":"Event"},"label":{"type":"string","title":"Label"},"role":{"type":"string","title":"Role"},"holders":{"type":"integer","title":"Holders"},"kind":{"type":"string","title":"Kind"}},"type":"object","required":["event","label","role","holders","kind"],"title":"OperationalRouteOut"},"OrderItemOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"product_id":{"type":"string","format":"uuid","title":"Product Id"},"name_snapshot":{"type":"string","title":"Name Snapshot"},"brand_snapshot":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand Snapshot"},"image_key_snapshot":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Key Snapshot"},"unit_price_cents":{"type":"integer","title":"Unit Price Cents"},"quantity":{"type":"integer","title":"Quantity"},"line_total_cents":{"type":"integer","title":"Line Total Cents"}},"type":"object","required":["id","product_id","name_snapshot","brand_snapshot","image_key_snapshot","unit_price_cents","quantity","line_total_cents"],"title":"OrderItemOut"},"OrderOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"reference":{"type":"string","title":"Reference"},"status":{"type":"string","title":"Status"},"fulfillment":{"type":"string","title":"Fulfillment"},"currency":{"type":"string","title":"Currency"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"business_name":{"type":"string","title":"Business Name"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"branch_name":{"type":"string","title":"Branch Name"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"items":{"items":{"$ref":"#/components/schemas/OrderItemOut"},"type":"array","title":"Items"},"subtotal_cents":{"type":"integer","title":"Subtotal Cents"},"discount_cents":{"type":"integer","title":"Discount Cents","default":0},"membership_plan_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Membership Plan Id"},"fee_cents":{"type":"integer","title":"Fee Cents"},"tax_cents":{"type":"integer","title":"Tax Cents"},"total_cents":{"type":"integer","title":"Total Cents"},"payment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Payment Id"},"client_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Note"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"paid_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Paid At"},"accepted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Accepted At"},"preparing_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Preparing At"},"ready_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ready At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"},"cancelled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Cancelled At"},"cancelled_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancelled Reason"},"refunded_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Refunded At"},"refunded_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Refunded Cents"},"pickup_window_starts_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Pickup Window Starts At"},"pickup_window_ends_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Pickup Window Ends At"},"receipt_lines":{"anyOf":[{"items":{"$ref":"#/components/schemas/OrderReceiptLineOut"},"type":"array"},{"type":"null"}],"title":"Receipt Lines"},"receipt_total_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Receipt Total Cents"}},"type":"object","required":["id","reference","status","fulfillment","currency","business_id","business_name","branch_id","branch_name","city","state","items","subtotal_cents","fee_cents","tax_cents","total_cents","payment_id","client_note","created_at","paid_at","ready_at","completed_at","cancelled_at","cancelled_reason"],"title":"OrderOut"},"OrderReceiptLineOut":{"properties":{"kind":{"type":"string","title":"Kind"},"label":{"type":"string","title":"Label"},"amount_cents":{"type":"integer","title":"Amount Cents"},"rate_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rate Bps"}},"type":"object","required":["kind","label","amount_cents"],"title":"OrderReceiptLineOut"},"OrderStatusIn":{"properties":{"status":{"type":"string","enum":["accepted","preparing","ready","completed","cancelled","refunded"],"title":"Status"},"note":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Note"}},"type":"object","required":["status"],"title":"OrderStatusIn","description":"The shop moving an order along, in his decision 46's order:\npaid → accepted → preparing → ready → completed. A shop may skip ahead —\nbagging a shampoo takes ten seconds and should not take three taps — but\nnever go back. 'cancelled' is refused once it has been paid for; see\nservice.ALLOWED_TRANSITIONS."},"OutdateIn":{"properties":{"reason":{"type":"string","maxLength":500,"minLength":3,"title":"Reason"}},"type":"object","required":["reason"],"title":"OutdateIn"},"OwedOut":{"properties":{"account":{"type":"string","title":"Account"},"amount_cents":{"type":"integer","title":"Amount Cents"},"entry_count":{"type":"integer","title":"Entry Count"},"oldest":{"type":"string","format":"date-time","title":"Oldest"},"newest":{"type":"string","format":"date-time","title":"Newest"}},"type":"object","required":["account","amount_cents","entry_count","oldest","newest"],"title":"OwedOut","description":"What is unpaid right now — the balance, before any payout is made."},"OwnProfessionalIn":{"properties":{"display_name":{"type":"string","maxLength":120,"minLength":2,"title":"Display Name"},"title":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Title"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio"},"avatar_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Key"},"years_experience":{"anyOf":[{"type":"integer","maximum":80.0,"minimum":0.0},{"type":"null"}],"title":"Years Experience"}},"type":"object","required":["display_name"],"title":"OwnProfessionalIn","description":"A person creating their OWN professional identity, with no shop.\n\nHis onboarding directive's Professional path — Welcome → Account → Verify →\nRoles → Profession → Personal → Personalization → Professional → Social →\nPortfolio → Review → Ready — has no business step in it, and should not: a\nbarber who rents a chair and a stylist who travels own nothing.\n\nNo `user_id` (it is the caller) and no `branch_id` (there is no branch). The\nprofile is theirs; being bookable is a separate, later fact that arrives with\na branch link."},"PayoutOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"account":{"type":"string","title":"Account"},"amount_cents":{"type":"integer","title":"Amount Cents"},"currency":{"type":"string","title":"Currency"},"status":{"type":"string","title":"Status"},"period_start":{"type":"string","format":"date-time","title":"Period Start"},"period_end":{"type":"string","format":"date-time","title":"Period End"},"provider_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Ref"},"failed_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failed Reason"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","account","amount_cents","currency","status","period_start","period_end","provider_ref","failed_reason","created_at"],"title":"PayoutOut","description":"A batch of what the ledger said was owed.\n\n'pending' means recorded, not sent: moving money needs Stripe Connect and the\nclient's account. Saying 'paid' with nothing behind it would put a lie in the\none record a professional would use to argue they were not paid."},"PayoutRowOut":{"properties":{"id":{"type":"string","title":"Id"},"account":{"type":"string","title":"Account"},"beneficiary_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Id"},"beneficiary_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Beneficiary Name"},"amount_cents":{"type":"integer","title":"Amount Cents"},"currency":{"type":"string","title":"Currency"},"status":{"type":"string","title":"Status"},"failed_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Failed Reason"},"provider_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Ref"},"period_start":{"type":"string","format":"date-time","title":"Period Start"},"period_end":{"type":"string","format":"date-time","title":"Period End"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"}},"type":"object","required":["id","account","beneficiary_id","beneficiary_name","amount_cents","currency","status","failed_reason","provider_ref","period_start","period_end","created_at","updated_at"],"title":"PayoutRowOut"},"PersonalizationIn":{"properties":{"option_keys":{"items":{"type":"string"},"type":"array","maxItems":30,"title":"Option Keys"}},"type":"object","title":"PersonalizationIn","description":"Every chip the person has ticked, across all three questions.\n\nTHE WHOLE SET, not the new ones: the screen is a set of toggles, and sending\nonly additions would make un-ticking impossible. An empty list is a valid\nanswer — his screen draws \"Skip for now\"."},"PersonalizationOptionOut":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"}},"type":"object","required":["key","label"],"title":"PersonalizationOptionOut"},"PersonalizationOut":{"properties":{"questions":{"items":{"$ref":"#/components/schemas/PersonalizationQuestionOut"},"type":"array","title":"Questions"},"answers":{"items":{"type":"string"},"type":"array","title":"Answers"}},"type":"object","required":["questions","answers"],"title":"PersonalizationOut"},"PersonalizationQuestionOut":{"properties":{"key":{"type":"string","title":"Key"},"prompt":{"type":"string","title":"Prompt"},"max_choices":{"type":"integer","title":"Max Choices"},"options":{"items":{"$ref":"#/components/schemas/PersonalizationOptionOut"},"type":"array","title":"Options"}},"type":"object","required":["key","prompt","max_choices","options"],"title":"PersonalizationQuestionOut","description":"One of his three, with only the options THIS person should see."},"PhoneStartIn":{"properties":{"phone":{"type":"string","maxLength":32,"title":"Phone"}},"type":"object","required":["phone"],"title":"PhoneStartIn"},"PhoneVerifyIn":{"properties":{"phone":{"type":"string","maxLength":32,"title":"Phone"},"code":{"type":"string","maxLength":10,"minLength":4,"title":"Code"}},"type":"object","required":["phone","code"],"title":"PhoneVerifyIn"},"PickupWindowIn":{"properties":{"starts_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Starts At"},"ends_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ends At"}},"type":"object","title":"PickupWindowIn","description":"The shop's estimate of when the order can be collected.\n\nBoth instants or neither: sending one alone is refused rather than stored,\nbecause \"ready between 3pm and —\" is worse than no estimate. Sending both\nas null CLEARS the estimate, which a shop that has changed its mind needs\nto be able to do."},"PlanOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"code":{"type":"string","title":"Code"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"audience":{"type":"string","title":"Audience"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"price_cents":{"type":"integer","title":"Price Cents"},"billing_period":{"type":"string","title":"Billing Period"},"benefits":{"additionalProperties":true,"type":"object","title":"Benefits","default":{}},"image_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Key"}},"type":"object","required":["id","code","name","description","audience","price_cents","billing_period"],"title":"PlanOut","description":"A membership card, as the client drew it.\n\n`benefits` is passed through whole rather than flattened into fixed fields: the\nbadge, the tagline and the bullet list are the client's copy, and the app should\nrender his words. A new perk is then a data change, not a schema change."},"PlatformAdministrationOut":{"properties":{"status":{"$ref":"#/components/schemas/PlatformStatusOut"},"roles":{"$ref":"#/components/schemas/RolesSummaryOut"},"security":{"$ref":"#/components/schemas/SecuritySummaryOut"},"integrations":{"items":{"$ref":"#/components/schemas/IntegrationOut"},"type":"array","title":"Integrations"},"money_settings":{"items":{"$ref":"#/components/schemas/MoneySettingOut"},"type":"array","title":"Money Settings"},"recent_activity":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Recent Activity"},"not_built":{"additionalProperties":{"type":"string"},"type":"object","title":"Not Built"},"generated_at":{"type":"string","format":"date-time","title":"Generated At"}},"type":"object","required":["status","roles","security","integrations","money_settings","recent_activity","not_built","generated_at"],"title":"PlatformAdministrationOut"},"PlatformInvoiceOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"subscription_id":{"type":"string","format":"uuid","title":"Subscription Id"},"plan_code":{"type":"string","title":"Plan Code"},"plan_name":{"type":"string","title":"Plan Name"},"period_start":{"type":"string","format":"date-time","title":"Period Start"},"period_end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Period End"},"currency":{"type":"string","title":"Currency"},"subtotal_cents":{"type":"integer","title":"Subtotal Cents"},"tax_cents":{"type":"integer","title":"Tax Cents"},"credits_cents":{"type":"integer","title":"Credits Cents"},"total_cents":{"type":"integer","title":"Total Cents"},"status":{"type":"string","title":"Status"},"paid_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Paid At"},"receipt_path":{"type":"string","title":"Receipt Path"}},"type":"object","required":["id","subscription_id","plan_code","plan_name","period_start","period_end","currency","subtotal_cents","tax_cents","credits_cents","total_cents","status","paid_at","receipt_path"],"title":"PlatformInvoiceOut","description":"HIS DECISION 101 — one paid period of the MyLook subscription, read from\nthe payment that landed: id, period, subtotal, tax, credits, total, status,\npayment date, receipt."},"PlatformPlanOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"code":{"type":"string","title":"Code"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"audience":{"type":"string","title":"Audience"},"price_cents":{"type":"integer","title":"Price Cents"},"billing_period":{"type":"string","title":"Billing Period"},"benefits":{"additionalProperties":true,"type":"object","title":"Benefits","default":{}}},"type":"object","required":["id","code","name","description","audience","price_cents","billing_period"],"title":"PlatformPlanOut","description":"A plan a PROFESSIONAL or a BUSINESS buys from MyLook.\n\nNot a customer membership. `audience` is always 'professional' or 'business'\nhere — the database refuses anything else on a platform subscription — and it\nis returned on every plan precisely so an SDK cannot mix the two lists up."},"PlatformStatusOut":{"properties":{"label":{"type":"string","title":"Label"},"all_ok":{"type":"boolean","title":"All Ok"},"items_need_review":{"type":"integer","title":"Items Need Review"},"pending_integrations":{"type":"integer","title":"Pending Integrations"},"staff_without_second_factor":{"type":"integer","title":"Staff Without Second Factor"}},"type":"object","required":["label","all_ok","items_need_review","pending_integrations","staff_without_second_factor"],"title":"PlatformStatusOut"},"PlatformSubscribeIn":{"properties":{"plan_id":{"type":"string","format":"uuid","title":"Plan Id"},"card_number":{"anyOf":[{"type":"string","maxLength":25},{"type":"null"}],"title":"Card Number"}},"type":"object","required":["plan_id"],"title":"PlatformSubscribeIn"},"PlatformSubscriptionOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"plan_id":{"type":"string","format":"uuid","title":"Plan Id"},"plan_audience":{"type":"string","title":"Plan Audience"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"professional_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Professional Id"},"status":{"type":"string","title":"Status"},"current_period_start":{"type":"string","format":"date-time","title":"Current Period Start"},"current_period_end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Current Period End"},"cancelled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Cancelled At"}},"type":"object","required":["id","plan_id","plan_audience","business_id","professional_id","status","current_period_start","current_period_end","cancelled_at"],"title":"PlatformSubscriptionOut"},"PlatformSubscriptionStateOut":{"properties":{"is_subscribed":{"type":"boolean","title":"Is Subscribed"},"plans_available":{"type":"integer","title":"Plans Available"},"subscription":{"anyOf":[{"$ref":"#/components/schemas/PlatformSubscriptionOut"},{"type":"null"}]}},"type":"object","required":["is_subscribed","plans_available"],"title":"PlatformSubscriptionStateOut","description":"Whether this business pays MyLook for the platform.\n\nCarries NO booking fee and NO service discount, on purpose: those are CONSUMER\nfigures and they are answered by GET /v1/me/membership. A platform\nsubscription grants neither."},"PopularServiceOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"price_cents":{"type":"integer","title":"Price Cents"},"cover_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cover Key"},"category_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Slug"},"category_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Name"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"business_slug":{"type":"string","title":"Business Slug"},"business_name":{"type":"string","title":"Business Name"},"business_is_verified":{"type":"boolean","title":"Business Is Verified"},"logo_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Key"},"business_cover_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Cover Key"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"branch_name":{"type":"string","title":"Branch Name"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"distance_miles":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance Miles"},"booking_count":{"type":"integer","title":"Booking Count"}},"type":"object","required":["id","name","description","duration_minutes","price_cents","cover_key","category_slug","category_name","business_id","business_slug","business_name","business_is_verified","logo_key","business_cover_key","branch_id","branch_name","city","state","distance_miles","booking_count"],"title":"PopularServiceOut","description":"One card in the client's \"Popular services\" row.\n\nEvery field is something his card actually draws — cover, price badge, service\nname, the shop's name, the duration, the distance — plus the branch it was\nfound at, without which the card cannot lead anywhere bookable.\n\n`booking_count` is the one addition, and it is deliberate: it is the evidence\nfor the word \"popular\". A rank the caller cannot check is a claim, not a\nmeasurement. Nothing else is invented; his card shows no rating and none is\nreturned.\n\nImages travel as object-storage KEYS, never URLs, exactly as every other card\non this platform does — the media domain turns a key into a signed address."},"PopularServicesOut":{"properties":{"ranked_by":{"type":"string","enum":["bookings","insufficient_data"],"title":"Ranked By"},"window_days":{"type":"integer","title":"Window Days"},"min_bookings":{"type":"integer","title":"Min Bookings"},"bookable_nearby":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Bookable Nearby"},"items":{"items":{"$ref":"#/components/schemas/PopularServiceOut"},"type":"array","title":"Items","default":[]}},"type":"object","required":["ranked_by","window_days","min_bookings"],"title":"PopularServicesOut","description":"The rail, with the honesty of its own ranking stated in the payload.\n\n`ranked_by` is 'bookings' when there was real demand to rank. It is\n'insufficient_data' when there was not — and then `items` is EMPTY rather than\nfilled with something else. A row titled \"Popular services\" that quietly\ndegrades into \"some services near you\" is a claim the app cannot tell apart\nfrom a real one, so the response makes the difference machine-readable."},"PortfolioItemIn":{"properties":{"media_id":{"type":"string","format":"uuid","title":"Media Id"},"section":{"type":"string","enum":["my_work","my_business","my_space","my_team","before_after"],"title":"Section","default":"my_work"},"caption":{"anyOf":[{"type":"string","maxLength":280},{"type":"null"}],"title":"Caption"},"make_cover":{"type":"boolean","title":"Make Cover","default":false},"visibility":{"type":"string","enum":["private","business_only","public"],"title":"Visibility","default":"private"}},"type":"object","required":["media_id"],"title":"PortfolioItemIn"},"PortfolioItemOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"media_id":{"type":"string","format":"uuid","title":"Media Id"},"section":{"type":"string","enum":["my_work","my_business","my_space","my_team","before_after"],"title":"Section"},"caption":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Caption"},"sort_order":{"type":"integer","title":"Sort Order"},"is_cover":{"type":"boolean","title":"Is Cover"},"visibility":{"type":"string","title":"Visibility","default":"private"},"media_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Media Key"},"url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Url"}},"type":"object","required":["id","media_id","section","caption","sort_order","is_cover"],"title":"PortfolioItemOut"},"ProductCardOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"image_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Key"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags","default":[]},"price_cents":{"type":"integer","title":"Price Cents"},"badge":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Badge"},"units_sold":{"type":"integer","title":"Units Sold","default":0},"net_units_sold":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Net Units Sold"},"net_revenue_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Net Revenue Cents"},"rating_avg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rating Avg"},"rating_count":{"type":"integer","title":"Rating Count","default":0},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"business_name":{"type":"string","title":"Business Name"},"business_slug":{"type":"string","title":"Business Slug"},"business_is_verified":{"type":"boolean","title":"Business Is Verified"},"logo_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Key"},"business_rating_avg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Business Rating Avg"},"business_rating_count":{"type":"integer","title":"Business Rating Count","default":0},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"branch_name":{"type":"string","title":"Branch Name"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"distance_miles":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance Miles"},"category_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Slug"},"category_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Name"},"in_stock":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"In Stock"},"stock_left":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Stock Left"},"variants":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Variants","default":[]},"variant_attribute":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Variant Attribute"}},"type":"object","required":["id","name","brand","description","image_key","price_cents","business_id","business_name","business_slug","business_is_verified","logo_key","branch_id","branch_name","city","state","latitude","longitude"],"title":"ProductCardOut","description":"One card on the client's Shop rail, with the shop it is sold at attached.\n\nA product without its shop is not something anyone can buy, so the branch\ntravels with it — that is also the branch the app sends back to Add to Cart."},"ProductCreateIn":{"properties":{"name":{"type":"string","maxLength":120,"minLength":2,"title":"Name"},"description":{"anyOf":[{"type":"string","maxLength":2000},{"type":"null"}],"title":"Description"},"brand":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Brand"},"sku":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Sku"},"category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Category Id"},"price_cents":{"type":"integer","exclusiveMinimum":0.0,"title":"Price Cents"},"barcode":{"anyOf":[{"type":"string","pattern":"^[0-9]{8,14}$"},{"type":"null"}],"title":"Barcode"},"status":{"type":"string","enum":["draft","published"],"title":"Status","default":"published"},"opening_stock":{"anyOf":[{"items":{"$ref":"#/components/schemas/OpeningStockIn"},"type":"array"},{"type":"null"}],"title":"Opening Stock"}},"type":"object","required":["name","price_cents"],"title":"ProductCreateIn","description":"Create or replace a product — Shop Manager STD-002 \"Product Payload\".\n\nVAL-007: the price is above zero. VAL-006: the SKU, when given, is unique within\nthe shop (the database's partial unique index is the guarantee; the service\nturns it into a 409). `status` is draft or published — archiving has its own\nroute — and BVL-005 is checked whenever a product is published.\n\n`status: \"published\"` is a REQUEST, not an instruction. His decision 81 —\n\"missing anything mandatory, it saves as Draft and the user sees exactly what\nis missing\" — means the record is kept either way and only the publication\nfails. Read `status` and `publish_blocked_by` on the way back."},"ProductDetailOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand"},"price_cents":{"type":"integer","title":"Price Cents"},"is_active":{"type":"boolean","title":"Is Active"},"status":{"type":"string","title":"Status","default":"published"},"sku":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sku"},"barcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Barcode"},"category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Category Id"},"image_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Key"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"publish_blocked_by":{"items":{"type":"string"},"type":"array","title":"Publish Blocked By","default":[]},"variants":{"items":{"$ref":"#/components/schemas/PublicVariantOut"},"type":"array","title":"Variants","default":[]},"variant_attribute":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Variant Attribute"},"category_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Name"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Archived At"},"inventory":{"items":{"$ref":"#/components/schemas/InventoryLevelOut"},"type":"array","title":"Inventory","default":[]},"unconfigured_branches":{"items":{"$ref":"#/components/schemas/UnconfiguredBranchOut"},"type":"array","title":"Unconfigured Branches","default":[]},"images":{"items":{"$ref":"#/components/schemas/ProductImageOut"},"type":"array","title":"Images","default":[]},"managed_variants":{"items":{"$ref":"#/components/schemas/VariantOut"},"type":"array","title":"Managed Variants","default":[]},"stock_state":{"type":"string","enum":["not_configured","out_of_stock","low_stock","in_stock","not_shown"],"title":"Stock State","default":"not_configured"},"stock_summary":{"type":"string","title":"Stock Summary","default":"Inventory not configured"},"total_quantity":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Quantity"},"sellable":{"type":"boolean","title":"Sellable","default":false},"events":{"items":{"$ref":"#/components/schemas/ProductEventOut"},"type":"array","title":"Events","default":[]},"adjustments":{"items":{"$ref":"#/components/schemas/InventoryAdjustmentOut"},"type":"array","title":"Adjustments","default":[]}},"type":"object","required":["id","business_id","name","description","brand","price_cents","is_active"],"title":"ProductDetailOut"},"ProductEventOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"action":{"type":"string","title":"Action"},"actor_id":{"type":"string","format":"uuid","title":"Actor Id"},"actor_role":{"type":"string","title":"Actor Role"},"before_state":{"additionalProperties":true,"type":"object","title":"Before State"},"after_state":{"additionalProperties":true,"type":"object","title":"After State"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","action","actor_id","actor_role","before_state","after_state","created_at"],"title":"ProductEventOut"},"ProductImageIn":{"properties":{"media_id":{"type":"string","format":"uuid","title":"Media Id"},"caption":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Caption"}},"type":"object","required":["media_id"],"title":"ProductImageIn","description":"Hang an ALREADY-UPLOADED photo on a product.\n\nThe bytes go to `POST /v1/media` with kind `product_photo`, which owns size\nlimits and content types; this takes the id it hands back. One upload can\nthen be used twice without being stored twice."},"ProductImageOrderIn":{"properties":{"image_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":20,"minItems":1,"title":"Image Ids"}},"type":"object","required":["image_ids"],"title":"ProductImageOrderIn","description":"EVERY photo of the product, in the order the shop wants them."},"ProductImageOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"media_id":{"type":"string","format":"uuid","title":"Media Id"},"image_key":{"type":"string","title":"Image Key"},"caption":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Caption"},"sort_order":{"type":"integer","title":"Sort Order","default":0},"is_cover":{"type":"boolean","title":"Is Cover","default":false},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"}},"type":"object","required":["id","media_id","image_key"],"title":"ProductImageOut"},"ProductManageOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand"},"price_cents":{"type":"integer","title":"Price Cents"},"is_active":{"type":"boolean","title":"Is Active"},"status":{"type":"string","title":"Status","default":"published"},"sku":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sku"},"barcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Barcode"},"category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Category Id"},"image_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Key"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"publish_blocked_by":{"items":{"type":"string"},"type":"array","title":"Publish Blocked By","default":[]},"variants":{"items":{"$ref":"#/components/schemas/PublicVariantOut"},"type":"array","title":"Variants","default":[]},"variant_attribute":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Variant Attribute"},"category_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Name"},"archived_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Archived At"},"inventory":{"items":{"$ref":"#/components/schemas/InventoryLevelOut"},"type":"array","title":"Inventory","default":[]},"unconfigured_branches":{"items":{"$ref":"#/components/schemas/UnconfiguredBranchOut"},"type":"array","title":"Unconfigured Branches","default":[]},"images":{"items":{"$ref":"#/components/schemas/ProductImageOut"},"type":"array","title":"Images","default":[]},"managed_variants":{"items":{"$ref":"#/components/schemas/VariantOut"},"type":"array","title":"Managed Variants","default":[]},"stock_state":{"type":"string","enum":["not_configured","out_of_stock","low_stock","in_stock","not_shown"],"title":"Stock State","default":"not_configured"},"stock_summary":{"type":"string","title":"Stock Summary","default":"Inventory not configured"},"total_quantity":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Total Quantity"},"sellable":{"type":"boolean","title":"Sellable","default":false}},"type":"object","required":["id","business_id","name","description","brand","price_cents","is_active"],"title":"ProductManageOut","description":"A product as the shop's own manager reads it: every status, with stock.\n\nHIS DECISION 83, RESOLVED ON THE SERVER. `stock_state` and `stock_summary`\nare computed here, once, so that every screen showing this product agrees\nabout it. Left to the apps, each list would rank the locations its own way —\nand the ranking that comes naturally (\"some of them have units, so we're\nfine\") is the one he forbade in the same sentence."},"ProductOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Brand"},"price_cents":{"type":"integer","title":"Price Cents"},"is_active":{"type":"boolean","title":"Is Active"},"status":{"type":"string","title":"Status","default":"published"},"sku":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sku"},"barcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Barcode"},"category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Category Id"},"image_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Key"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At"},"updated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Updated At"},"publish_blocked_by":{"items":{"type":"string"},"type":"array","title":"Publish Blocked By","default":[]},"variants":{"items":{"$ref":"#/components/schemas/PublicVariantOut"},"type":"array","title":"Variants","default":[]},"variant_attribute":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Variant Attribute"}},"type":"object","required":["id","business_id","name","description","brand","price_cents","is_active"],"title":"ProductOut"},"ProfessionOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"sort_order":{"type":"integer","title":"Sort Order"},"icon":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Icon"}},"type":"object","required":["id","slug","name","sort_order"],"title":"ProfessionOut","description":"One profession. `icon` is the NAME of one, never an image: the app owns its icon set, and\na platform that shipped icon bytes would be shipping a design decision (his §16)."},"ProfessionalBranchOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"professional_id":{"type":"string","format":"uuid","title":"Professional Id"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"is_active":{"type":"boolean","title":"Is Active"},"started_at":{"type":"string","format":"date","title":"Started At"},"ended_at":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Ended At"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"},"consent":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Consent"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"accepted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Accepted At"},"activated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Activated At"}},"type":"object","required":["id","professional_id","branch_id","is_active","started_at","ended_at"],"title":"ProfessionalBranchOut"},"ProfessionalCreateIn":{"properties":{"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Phone"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"title":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Title"},"display_name":{"anyOf":[{"type":"string","maxLength":120,"minLength":2},{"type":"null"}],"title":"Display Name"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio"},"avatar_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Key"},"years_experience":{"anyOf":[{"type":"integer","maximum":80.0,"minimum":0.0},{"type":"null"}],"title":"Years Experience"}},"type":"object","required":["branch_id"],"title":"ProfessionalCreateIn","description":"Add a professional to a location — CR-SEC-2026-09-14-03.\n\n\"NO CONSENT, NO AUTHORITY.\" This route never starts a relationship with somebody who has not\nagreed to one. It does two things only:\n\n  · an owner links THEIR OWN identity at their own business — his decision 4, accepted by\n    definition and not bookable until activated;\n  · another location for somebody already on this team — his decision 7, \"location\n    assignment belongs to the business relationship\".\n\nAnybody else is invited (POST /businesses/{id}/invitations) and joins when they accept; asking\nhere answers 409 `invitation_required`.\n\nThe person is named the ways an invitation names them (his decisions 25 and 11). The profile's\nname, bio, photo and years belong to the PERSON (decision 7), so they are accepted only for an\nowner creating their own profile; `title` is the title at this business."},"ProfessionalDayOut":{"properties":{"date":{"type":"string","format":"date","title":"Date"},"timezone":{"type":"string","title":"Timezone"},"professional_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Professional Id"},"locations":{"items":{"$ref":"#/components/schemas/WorkPlaceOut"},"type":"array","title":"Locations"},"summary":{"additionalProperties":{"type":"integer"},"type":"object","title":"Summary"},"off":{"anyOf":[{"$ref":"#/components/schemas/DayOffOut"},{"type":"null"}]},"appointments":{"items":{"$ref":"#/components/schemas/DayBookingOut"},"type":"array","title":"Appointments"},"blocks":{"items":{"$ref":"#/components/schemas/DayBlockOut"},"type":"array","title":"Blocks"},"open_time":{"items":{"$ref":"#/components/schemas/OpenGapOut"},"type":"array","title":"Open Time"}},"type":"object","required":["date","timezone"],"title":"ProfessionalDayOut"},"ProfessionalDetailOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"display_name":{"type":"string","title":"Display Name"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"business_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Title"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio"},"avatar_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Key"},"years_experience":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Years Experience"},"is_verified":{"type":"boolean","title":"Is Verified"},"is_accepting_bookings":{"type":"boolean","title":"Is Accepting Bookings"},"rating_avg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rating Avg"},"rating_count":{"type":"integer","title":"Rating Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"branches":{"items":{"$ref":"#/components/schemas/ProfessionalBranchOut"},"type":"array","title":"Branches","default":[]}},"type":"object","required":["id","display_name","title","bio","avatar_key","years_experience","is_verified","is_accepting_bookings","rating_avg","rating_count","created_at"],"title":"ProfessionalDetailOut"},"ProfessionalLocationOut":{"properties":{"business_id":{"type":"string","format":"uuid","title":"Business Id"},"business_name":{"type":"string","title":"Business Name"},"business_slug":{"type":"string","title":"Business Slug"},"business_is_verified":{"type":"boolean","title":"Business Is Verified"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"branch_name":{"type":"string","title":"Branch Name"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"distance_miles":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance Miles"},"is_default":{"type":"boolean","title":"Is Default"}},"type":"object","required":["business_id","business_name","business_slug","business_is_verified","branch_id","branch_name","city","state","latitude","longitude","distance_miles","is_default"],"title":"ProfessionalLocationOut","description":"One public location a professional works at — HIS DIRECTIVE 4 par.06.\n\n    ONE PROFESSIONAL PROFILE -> BRANCH / LOCATION CONTEXT -> SERVICES AT THAT\n    LOCATION -> PRICE AT THAT LOCATION -> AVAILABILITY AT THAT LOCATION -> BOOKING\n\nThe profile is never duplicated; this is the selector the app draws when the\nsame person works at more than one shop. `is_default` marks the one the\nprofile opens on: the nearest when the caller sent a position, otherwise the\noldest link. A location that goes inactive (branch closed, shop suspended,\nlink ended) simply stops appearing here."},"ProfessionalNoteIn":{"properties":{"note":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Note"}},"type":"object","title":"ProfessionalNoteIn","description":"His \"Professional Notes (Internal)\". Empty or null clears it. The same\nlength as the client's own note."},"ProfessionalOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"display_name":{"type":"string","title":"Display Name"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"business_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Title"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio"},"avatar_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Key"},"years_experience":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Years Experience"},"is_verified":{"type":"boolean","title":"Is Verified"},"is_accepting_bookings":{"type":"boolean","title":"Is Accepting Bookings"},"rating_avg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rating Avg"},"rating_count":{"type":"integer","title":"Rating Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","display_name","title","bio","avatar_key","years_experience","is_verified","is_accepting_bookings","rating_avg","rating_count","created_at"],"title":"ProfessionalOut","description":"A professional profile.\n\nNO user_id — his decision 11 (CR-SEC-2026-09-14-03): \"remove them from public team exposure\".\nThis shape is served by the business's public team list, and the account id behind a person\nwas the handle a stranger business used to take them onto its team. The staff review queue,\nwhich decides about the ACCOUNT, still carries it (ProfessionalReviewOut)."},"ProfessionalPublicReviewOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"rating":{"type":"integer","title":"Rating"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"service_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Name"},"response":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Response"},"responded_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Responded At"}},"type":"object","required":["id","rating","created_at"],"title":"ProfessionalPublicReviewOut","description":"HIS DECISION 146 — \"Deben coincidir con professional_id. Nunca copiar\nreviews del negocio.\"\n\nA professional's reputation is theirs. Showing the shop's reviews on their\npage would credit them with work they may never have done, and would follow\nthem out of the door when they left. Every row here was written about an\nappointment THIS professional performed.\n\nNOBODY IS NAMED here, exactly as on the public business listing: a review is\npublic, the person who wrote it is not."},"ProfessionalReviewOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"display_name":{"type":"string","title":"Display Name"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"business_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Title"},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio"},"avatar_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Key"},"years_experience":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Years Experience"},"is_verified":{"type":"boolean","title":"Is Verified"},"is_accepting_bookings":{"type":"boolean","title":"Is Accepting Bookings"},"rating_avg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rating Avg"},"rating_count":{"type":"integer","title":"Rating Count"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"user_id":{"type":"string","format":"uuid","title":"User Id"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"business_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Name"},"business_is_verified":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Business Is Verified"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"branch_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch Name"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"last_action":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Action"},"last_action_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last Action At"},"last_action_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Action Reason"}},"type":"object","required":["id","display_name","title","bio","avatar_key","years_experience","is_verified","is_accepting_bookings","rating_avg","rating_count","created_at","user_id"],"title":"ProfessionalReviewOut","description":"One row of MyLook's professional review queue — staff only.\n\nKeeps user_id, which the public search shape deliberately drops: deciding\nwhether somebody is who they say they are is a question about the ACCOUNT\nbehind the profile, not about the card. It carries no money of any kind,\nfor the same reason nothing outside the earnings routes does."},"ProfessionalSearchOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"display_name":{"type":"string","title":"Display Name"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"avatar_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Key"},"years_experience":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Years Experience"},"is_verified":{"type":"boolean","title":"Is Verified"},"is_accepting_bookings":{"type":"boolean","title":"Is Accepting Bookings"},"rating_avg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rating Avg"},"rating_count":{"type":"integer","title":"Rating Count"},"work":{"items":{"$ref":"#/components/schemas/PublicWorkOut"},"type":"array","title":"Work"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"business_slug":{"type":"string","title":"Business Slug"},"business_name":{"type":"string","title":"Business Name"},"business_is_verified":{"type":"boolean","title":"Business Is Verified"},"logo_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Logo Key"},"category_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Slug"},"category_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Name"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"branch_name":{"type":"string","title":"Branch Name"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"distance_miles":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance Miles"},"locations":{"items":{"$ref":"#/components/schemas/ProfessionalLocationOut"},"type":"array","title":"Locations","default":[]},"bio":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Bio"},"specialties":{"items":{"$ref":"#/components/schemas/SpecialtyOut"},"type":"array","title":"Specialties","default":[]},"languages":{"items":{"$ref":"#/components/schemas/malu__domains__professionals__schemas__LanguageOut"},"type":"array","title":"Languages","default":[]}},"type":"object","required":["id","display_name","title","avatar_key","years_experience","is_verified","is_accepting_bookings","rating_avg","rating_count","business_id","business_slug","business_name","business_is_verified","logo_key","category_slug","category_name","branch_id","branch_name","city","state","latitude","longitude","distance_miles"],"title":"ProfessionalSearchOut","description":"One card in Discover's \"Featured Professionals near you\".\n\nFlat and complete: the shop travels with the person, because \"Ana Rivera,\n4.9 stars\" is not something anybody can book. One request draws twenty cards.\n\nNOT HERE, and never: any amount of money. No earnings, no compensation model,\nno rent, not even the \"from $X\" the BUSINESS card carries. The client's rule\nis that nobody but a chair-rent professional may see their sales, clients or\ntips, and a public endpoint has no caller to check that against\n(organization/permissions.py → can_view_professional_earnings). So the search\nbehind this shape reads no financial table at all.\n\nuser_id is absent too. It is the account behind the profile, of no use to a\nstranger browsing, and this endpoint is open to anyone."},"ProfessionalServiceOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Category Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"price_cents":{"type":"integer","title":"Price Cents"},"deposit_cents":{"type":"integer","title":"Deposit Cents"},"buffer_minutes":{"type":"integer","title":"Buffer Minutes"},"is_active":{"type":"boolean","title":"Is Active","default":true}},"type":"object","required":["id","business_id","category_id","name","description","duration_minutes","price_cents","deposit_cents","buffer_minutes"],"title":"ProfessionalServiceOut","description":"One service a professional performs, for their PUBLIC profile\n(PRO-PUBLIC-001, directive 3 §12: profile → services → availability → booking).\n\nDeliberately the shape of the catalog's `ServiceOut`, so the app reads it with\nthe SAME model the shop page uses (reuse before creation). `price_cents` is\nwhat a client pays AT THE BRANCH the professional works at — the catalog's\nown rule (branch override, else the business price), which is also what\nbooking charges; never a professional's private price. `duration_minutes` is\nthe professional's own when they set one, else the service's — the same\nnumber the availability calculation uses."},"ProfessionalUpdateIn":{"properties":{"display_name":{"anyOf":[{"type":"string","maxLength":120,"minLength":2},{"type":"null"}],"title":"Display Name"},"title":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Title"},"bio":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Bio"},"avatar_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Key"},"years_experience":{"anyOf":[{"type":"integer","maximum":80.0,"minimum":0.0},{"type":"null"}],"title":"Years Experience"},"is_accepting_bookings":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Accepting Bookings"},"specialties":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Specialties"},"languages":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Languages"}},"type":"object","title":"ProfessionalUpdateIn","description":"What a professional's profile can become after it is created.\n\nOmitting a field leaves it alone; sending null clears it — so a professional\nediting their bio cannot accidentally wipe their title.\n\nis_accepting_bookings is the one that matters day to day. Someone who is ill,\naway, or simply full needs to stop new bookings without being removed from the\nteam, and until now there was no way to say so at all.\n\nis_verified is absent on purpose: the tick is MyLook's to grant, and a profile\nthat can verify itself verifies nothing."},"ProfessionsIn":{"properties":{"slugs":{"items":{"type":"string"},"type":"array","maxItems":12,"minItems":1,"title":"Slugs"}},"type":"object","required":["slugs"],"title":"ProfessionsIn","description":"What this professional does. The FIRST slug is the primary one — his\nscreen badges it, and the order in the list is what says so, rather than a\nseparate field the app could get out of step with the badge it drew."},"PromotionCardOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"badge_label":{"type":"string","title":"Badge Label"},"headline":{"type":"string","title":"Headline"},"subtitle":{"type":"string","title":"Subtitle"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"image_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Key"},"sort_order":{"type":"integer","title":"Sort Order"},"discount_kind":{"type":"string","title":"Discount Kind"},"discount_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Discount Bps"},"discount_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Discount Cents"},"scope":{"type":"string","title":"Scope"},"category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Category Id"},"service_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Service Ids","default":[]},"audience":{"type":"string","title":"Audience"},"starts_at":{"type":"string","format":"date-time","title":"Starts At"},"ends_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ends At"},"max_redemptions":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Redemptions"},"per_client_limit":{"type":"integer","title":"Per Client Limit"},"stacks_with_membership":{"type":"boolean","title":"Stacks With Membership"},"is_active":{"type":"boolean","title":"Is Active"},"is_live":{"type":"boolean","title":"Is Live"},"redeemed_count":{"type":"integer","title":"Redeemed Count","default":0},"business_name":{"type":"string","title":"Business Name"},"business_slug":{"type":"string","title":"Business Slug"},"business_logo_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Logo Key"},"branch_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch Name"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"latitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Latitude"},"longitude":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Longitude"},"distance_miles":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Distance Miles"},"category_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Slug"},"category_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Category Name"}},"type":"object","required":["id","business_id","branch_id","badge_label","headline","subtitle","description","image_key","sort_order","discount_kind","discount_bps","discount_cents","scope","category_id","audience","starts_at","ends_at","max_redemptions","per_client_limit","stacks_with_membership","is_active","is_live","business_name","business_slug"],"title":"PromotionCardOut","description":"One card on the Discover rail.\n\nAn offer with no shop attached is not bookable, so the business and the location\ntravel with it — \"Book Now\" has to go somewhere."},"PromotionCreateIn":{"properties":{"badge_label":{"type":"string","maxLength":40,"minLength":2,"title":"Badge Label"},"subtitle":{"type":"string","maxLength":80,"minLength":2,"title":"Subtitle"},"description":{"anyOf":[{"type":"string","maxLength":400},{"type":"null"}],"title":"Description"},"image_key":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Image Key"},"sort_order":{"type":"integer","maximum":999.0,"minimum":0.0,"title":"Sort Order","default":0},"discount_kind":{"type":"string","enum":["percent","amount"],"title":"Discount Kind","default":"percent"},"discount_bps":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Discount Bps"},"discount_cents":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Discount Cents"},"scope":{"type":"string","enum":["all_services","category","service"],"title":"Scope","default":"all_services"},"category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Category Id"},"service_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":50,"title":"Service Ids"},"audience":{"type":"string","enum":["everyone","new_clients"],"title":"Audience","default":"everyone"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"starts_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Starts At"},"ends_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ends At"},"max_redemptions":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Max Redemptions"},"per_client_limit":{"type":"integer","maximum":1000.0,"minimum":1.0,"title":"Per Client Limit","default":1},"stacks_with_membership":{"type":"boolean","title":"Stacks With Membership","default":false}},"type":"object","required":["badge_label","subtitle"],"title":"PromotionCreateIn","description":"Publish an offer.\n\nThe two cards on the client's Discover screen are:\n\n    {\"badge_label\": \"LIMITED TIME\", \"subtitle\": \"All Hair Services\",\n     \"discount_bps\": 2000, \"scope\": \"category\", \"category_id\": <hair-salon>}\n\n    {\"badge_label\": \"NEW CLIENTS\", \"subtitle\": \"Gel & Nail Art\",\n     \"discount_bps\": 1500, \"scope\": \"service\", \"service_ids\": [...],\n     \"audience\": \"new_clients\"}\n\nNothing here carries a price: what a service costs is read from the catalog at\nthe location it is booked at. A caller who could send the price could send any\nprice."},"PromotionOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"badge_label":{"type":"string","title":"Badge Label"},"headline":{"type":"string","title":"Headline"},"subtitle":{"type":"string","title":"Subtitle"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"image_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Image Key"},"sort_order":{"type":"integer","title":"Sort Order"},"discount_kind":{"type":"string","title":"Discount Kind"},"discount_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Discount Bps"},"discount_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Discount Cents"},"scope":{"type":"string","title":"Scope"},"category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Category Id"},"service_ids":{"items":{"type":"string","format":"uuid"},"type":"array","title":"Service Ids","default":[]},"audience":{"type":"string","title":"Audience"},"starts_at":{"type":"string","format":"date-time","title":"Starts At"},"ends_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ends At"},"max_redemptions":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Max Redemptions"},"per_client_limit":{"type":"integer","title":"Per Client Limit"},"stacks_with_membership":{"type":"boolean","title":"Stacks With Membership"},"is_active":{"type":"boolean","title":"Is Active"},"is_live":{"type":"boolean","title":"Is Live"},"redeemed_count":{"type":"integer","title":"Redeemed Count","default":0}},"type":"object","required":["id","business_id","branch_id","badge_label","headline","subtitle","description","image_key","sort_order","discount_kind","discount_bps","discount_cents","scope","category_id","audience","starts_at","ends_at","max_redemptions","per_client_limit","stacks_with_membership","is_active","is_live"],"title":"PromotionOut"},"PromotionQuoteIn":{"properties":{"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"service_id":{"type":"string","format":"uuid","title":"Service Id"},"tip_cents":{"type":"integer","minimum":0.0,"title":"Tip Cents","default":0},"use_credit":{"type":"boolean","title":"Use Credit","default":false}},"type":"object","required":["branch_id","service_id"],"title":"PromotionQuoteIn","description":"What this offer does to this booking.\n\nThe service and the location are named; the PRICE is not, and cannot be. It is\nread from the catalog on the server."},"PromotionQuoteOut":{"properties":{"promotion_id":{"type":"string","format":"uuid","title":"Promotion Id"},"headline":{"type":"string","title":"Headline"},"service_id":{"type":"string","format":"uuid","title":"Service Id"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"service_cents":{"type":"integer","title":"Service Cents"},"discount_cents":{"type":"integer","title":"Discount Cents"},"credit_cents":{"type":"integer","title":"Credit Cents"},"booking_fee_cents":{"type":"integer","title":"Booking Fee Cents"},"tax_cents":{"type":"integer","title":"Tax Cents"},"tip_cents":{"type":"integer","title":"Tip Cents"},"total_cents":{"type":"integer","title":"Total Cents"},"lines":{"items":{"$ref":"#/components/schemas/QuoteLineOut"},"type":"array","title":"Lines"},"membership_discount_bps":{"type":"integer","title":"Membership Discount Bps"},"stacked_with_membership":{"type":"boolean","title":"Stacked With Membership"},"total_without_promotion_cents":{"type":"integer","title":"Total Without Promotion Cents"}},"type":"object","required":["promotion_id","headline","service_id","branch_id","service_cents","discount_cents","credit_cents","booking_fee_cents","tax_cents","tip_cents","total_cents","lines","membership_discount_bps","stacked_with_membership","total_without_promotion_cents"],"title":"PromotionQuoteOut","description":"The same shape money returns for any quote, plus what the offer contributed.\n\nEvery figure here comes from malu.domains.money.service.build_quote — the one\nfunction allowed to decide what somebody pays. This endpoint's own work is\ndeciding whether the caller is entitled to the discount and how big it is; the\ncomposition of the bill is not its business."},"PromotionUpdateIn":{"properties":{"badge_label":{"anyOf":[{"type":"string","maxLength":40,"minLength":2},{"type":"null"}],"title":"Badge Label"},"subtitle":{"anyOf":[{"type":"string","maxLength":80,"minLength":2},{"type":"null"}],"title":"Subtitle"},"description":{"anyOf":[{"type":"string","maxLength":400},{"type":"null"}],"title":"Description"},"image_key":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Image Key"},"sort_order":{"anyOf":[{"type":"integer","maximum":999.0,"minimum":0.0},{"type":"null"}],"title":"Sort Order"},"discount_bps":{"anyOf":[{"type":"integer","maximum":10000.0,"minimum":1.0},{"type":"null"}],"title":"Discount Bps"},"discount_cents":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Discount Cents"},"starts_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Starts At"},"ends_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ends At"},"max_redemptions":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Max Redemptions"},"per_client_limit":{"anyOf":[{"type":"integer","maximum":1000.0,"minimum":1.0},{"type":"null"}],"title":"Per Client Limit"},"stacks_with_membership":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Stacks With Membership"},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"}},"type":"object","title":"PromotionUpdateIn","description":"Edit an offer that is already published.\n\nWhat an offer IS — the kind of discount, what it covers, whose it is — cannot be\nchanged here. Redemptions already recorded refer to the terms in force when they\nhappened, and quietly turning \"20% off hair\" into \"$40 off everything\" would\nrewrite the meaning of history rather than replace the offer. A different offer\nis a new row."},"PublicArticleOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"title":{"type":"string","title":"Title"},"domain":{"type":"string","title":"Domain"},"domain_label":{"type":"string","title":"Domain Label"},"language":{"type":"string","title":"Language"},"version":{"type":"string","title":"Version"},"summary":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Summary"},"tags":{"items":{"type":"string"},"type":"array","title":"Tags"},"published_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Published At"},"updated_at":{"type":"string","format":"date-time","title":"Updated At"},"blocks":{"items":{"$ref":"#/components/schemas/PublicBlockOut"},"type":"array","title":"Blocks"}},"type":"object","required":["id","code","title","domain","domain_label","language","version","summary","tags","published_at","updated_at"],"title":"PublicArticleOut","description":"What a customer or a professional reads: no authors, no internal state."},"PublicBlockOut":{"properties":{"kind":{"type":"string","title":"Kind"},"title":{"type":"string","title":"Title"},"body":{"type":"string","title":"Body"}},"type":"object","required":["kind","title","body"],"title":"PublicBlockOut"},"PublicPortfolioItemOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"section":{"type":"string","title":"Section"},"caption":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Caption"},"sort_order":{"type":"integer","title":"Sort Order"},"is_cover":{"type":"boolean","title":"Is Cover"},"media_key":{"type":"string","title":"Media Key"},"url":{"type":"string","title":"Url"},"professional_id":{"type":"string","format":"uuid","title":"Professional Id"},"professional_name":{"type":"string","title":"Professional Name"},"visibility":{"type":"string","title":"Visibility","default":"public"}},"type":"object","required":["id","section","sort_order","is_cover","media_key","url","professional_id","professional_name"],"title":"PublicPortfolioItemOut"},"PublicReviewOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"rating":{"type":"integer","title":"Rating"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment"},"service_quality":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Service Quality"},"cleanliness":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cleanliness"},"punctuality":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Punctuality"},"photo_keys":{"items":{"type":"string"},"type":"array","title":"Photo Keys","default":[]},"is_published":{"type":"boolean","title":"Is Published"},"state":{"type":"string","title":"State","default":"published"},"state_changed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"State Changed At"},"edited_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Edited At"},"removal_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Removal Reason"},"attributes":{"items":{"type":"string"},"type":"array","title":"Attributes","default":[]},"media_consent":{"type":"boolean","title":"Media Consent","default":false},"media_consent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Media Consent At"},"media_consent_revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Media Consent Revoked At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"response":{"anyOf":[{"$ref":"#/components/schemas/PublicReviewResponseOut"},{"type":"null"}]}},"type":"object","required":["id","rating","comment","service_quality","cleanliness","punctuality","is_published","created_at"],"title":"PublicReviewOut","description":"A review as ANYBODY reads it, signed in or not — CR-PRIV-2026-09-14-01, authorized 2026-09-14\n(owner question 174): \"remove internal account identifiers from public reviews/responses\".\n\nAN ALLOWLIST, not ReviewOut with a field taken away: a field reaches a signed-out visitor only when\nit is written here, so what ReviewOut gains for the author or the business does not become public by\ndefault. No account id: not the client who wrote it, not the team member who answered. The author's\nown routes, the business's inbox and moderation keep ReviewOut.\n\nHIS ANSWER OF 2026-09-14: \"The public review API must expose only identifiers required for the public\nexperience. If navigation requires identity, use the public/opaque review_id; do not expose the\ninternal appointment identifier.\" So the one id here is the review's own — no visit, business,\nlocation or professional id: the page that lists these already knows which business it is showing."},"PublicReviewResponseOut":{"properties":{"body":{"type":"string","title":"Body"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["body","created_at"],"title":"PublicReviewResponseOut","description":"The business's reply as ANYBODY reads it — CR-PRIV-2026-09-14-01, owner question 174.\n\nIt is published under the business's name, so the account of the team member who typed it\n(`ReviewResponseOut.author_id`) is not part of it — and since his answer of 2026-09-14 neither are\nits own ids: it sits inside the review it answers, and a public page needs its words and its date."},"PublicVariantOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"label":{"type":"string","title":"Label"},"price_cents":{"type":"integer","title":"Price Cents"},"in_stock":{"type":"boolean","title":"In Stock"}},"type":"object","required":["id","label","price_cents","in_stock"],"title":"PublicVariantOut","description":"What a CLIENT sees of a variant, and no more.\n\nNo SKU and no barcode: those are the shop's internal codes, and a public read\nthat carries them tells strangers how a shop labels its stock.\n\nTHE PRICE IS RESOLVED — the variant's when it set one, the product's\notherwise — because a client should not have to know the platform's\ninheritance rule to read a price.\n\nDefined ABOVE ProductOut on purpose: FastAPI builds the response TypeAdapter\nat import, so a forward reference to a class further down the file makes\nevery read of that model a 500 rather than an import error."},"PublicWorkOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"work_type":{"type":"string","enum":["business","chair","suite","independent_studio","mobile","client_home"],"title":"Work Type"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"business_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Name"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"branch_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch Name"},"chair_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chair Number"},"booth_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Booth Number"},"floor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Floor"},"place_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Name"},"suite_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Suite Number"},"street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code"},"public_directions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Public Directions"},"entrance_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entrance Notes"},"service_radius_miles":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Service Radius Miles"},"service_areas":{"items":{"type":"string"},"type":"array","title":"Service Areas"},"travel_fee_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Travel Fee Cents"},"minimum_booking_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Minimum Booking Cents"}},"type":"object","required":["id","work_type"],"title":"PublicWorkOut","description":"HOW THIS PERSON WORKS, as a client may read it — MY PROFILE v1.1 section 2.\n\nThe projection of one published `professional_work_setups` row: his words, none of ours. The\nstreet appears only when the professional turned their address on, and never for the two\ntravelling types; the city and the state are here either way, because a client chooses by\nwhere somebody works. The LABEL (\"Chair Professional\", \"Mobile Professional\") is the app's own\ncopy, from `work_type` — a server does not hold UI words (his multilingual directive)."},"PublishIn":{"properties":{"major":{"type":"boolean","title":"Major","default":false}},"type":"object","title":"PublishIn"},"PulseFigureOut":{"properties":{"value":{"anyOf":[{"type":"integer"},{"type":"string"},{"type":"null"}],"title":"Value"},"basis":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Basis"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","title":"PulseFigureOut","description":"One of his five, and the reason when there is no number.\n\nTHE REASON IS PART OF THE ANSWER. His decision 26 ends \"without enough\nbasis, show 'Not enough data' — never invent 92%\", and a null with no\nexplanation is how a screen ends up inventing one anyway: somebody fills the\ngap with something plausible because nothing said why it was empty."},"QueueItemOut":{"properties":{"kind":{"type":"string","title":"Kind"},"kind_label":{"type":"string","title":"Kind Label"},"id":{"type":"string","title":"Id"},"title":{"type":"string","title":"Title"},"subtitle":{"type":"string","title":"Subtitle"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"age_seconds":{"type":"integer","title":"Age Seconds"},"href":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Href"},"severity":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Severity"},"rank":{"type":"integer","title":"Rank"},"sla_at_risk":{"type":"boolean","title":"Sla At Risk","default":false}},"type":"object","required":["kind","kind_label","id","title","subtitle","created_at","age_seconds","href","severity","rank"],"title":"QueueItemOut"},"QuoteIn":{"properties":{"service_cents":{"type":"integer","minimum":0.0,"title":"Service Cents"},"tip_cents":{"type":"integer","minimum":0.0,"title":"Tip Cents","default":0},"discount_cents":{"type":"integer","minimum":0.0,"title":"Discount Cents","default":0},"use_credit":{"type":"boolean","title":"Use Credit","default":false}},"type":"object","required":["service_cents"],"title":"QuoteIn","description":"Preview what a booking will cost, before any money moves."},"QuoteLineOut":{"properties":{"kind":{"type":"string","title":"Kind"},"label":{"type":"string","title":"Label"},"amount_cents":{"type":"integer","title":"Amount Cents"},"rate_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rate Bps"}},"type":"object","required":["kind","label","amount_cents"],"title":"QuoteLineOut"},"QuoteOut":{"properties":{"service_cents":{"type":"integer","title":"Service Cents"},"discount_cents":{"type":"integer","title":"Discount Cents"},"credit_cents":{"type":"integer","title":"Credit Cents"},"booking_fee_cents":{"type":"integer","title":"Booking Fee Cents"},"tax_cents":{"type":"integer","title":"Tax Cents"},"tip_cents":{"type":"integer","title":"Tip Cents"},"total_cents":{"type":"integer","title":"Total Cents"},"lines":{"items":{"$ref":"#/components/schemas/QuoteLineOut"},"type":"array","title":"Lines"}},"type":"object","required":["service_cents","discount_cents","credit_cents","booking_fee_cents","tax_cents","tip_cents","total_cents","lines"],"title":"QuoteOut"},"RankedBusinessOut":{"properties":{"rank":{"type":"integer","title":"Rank"},"score":{"type":"number","title":"Score"},"explanation":{"type":"string","title":"Explanation"},"business":{"$ref":"#/components/schemas/BusinessSearchOut"}},"type":"object","required":["rank","score","explanation","business"],"title":"RankedBusinessOut","description":"One position in a server-owned ranking: the card, its rank, its score and\nthe sentence that explains the score (directive 3 §6: explainability)."},"RatingSummaryOut":{"properties":{"business_id":{"type":"string","format":"uuid","title":"Business Id"},"rating_avg":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Rating Avg"},"rating_count":{"type":"integer","title":"Rating Count"}},"type":"object","required":["business_id","rating_avg","rating_count"],"title":"RatingSummaryOut","description":"The denormalised aggregate the discovery screens read off `businesses`."},"ReceiptLineOut":{"properties":{"kind":{"type":"string","title":"Kind"},"label":{"type":"string","title":"Label"},"amount_cents":{"type":"integer","title":"Amount Cents"},"rate_bps":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Rate Bps"}},"type":"object","required":["kind","label","amount_cents"],"title":"ReceiptLineOut"},"ReceiptOut":{"properties":{"payment_id":{"type":"string","title":"Payment Id"},"appointment_id":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Appointment Id"},"status":{"type":"string","title":"Status"},"currency":{"type":"string","title":"Currency"},"card_brand":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Card Brand"},"card_last4":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Card Last4"},"paid_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Paid At"},"lines":{"items":{"$ref":"#/components/schemas/ReceiptLineOut"},"type":"array","title":"Lines"},"lines_total_cents":{"type":"integer","title":"Lines Total Cents"},"total_cents":{"type":"integer","title":"Total Cents"},"refunded_cents":{"type":"integer","title":"Refunded Cents"}},"type":"object","required":["payment_id","appointment_id","status","currency","card_brand","card_last4","paid_at","lines","lines_total_cents","total_cents","refunded_cents"],"title":"ReceiptOut"},"RecommendationOut":{"properties":{"why":{"type":"string","title":"Why"},"business":{"$ref":"#/components/schemas/BusinessSearchOut"}},"type":"object","required":["why","business"],"title":"RecommendationOut"},"RecommendationsOut":{"properties":{"basis":{"type":"string","enum":["history","insufficient_history","personalization_off"],"title":"Basis"},"engine":{"type":"string","title":"Engine"},"generated_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Generated At"},"items":{"items":{"$ref":"#/components/schemas/RecommendationOut"},"type":"array","title":"Items","default":[]},"fallback_order":{"items":{"type":"string"},"type":"array","title":"Fallback Order","default":[]}},"type":"object","required":["basis","engine"],"title":"RecommendationsOut"},"RecoveryCodesOut":{"properties":{"recovery_codes":{"items":{"type":"string"},"type":"array","title":"Recovery Codes"}},"type":"object","required":["recovery_codes"],"title":"RecoveryCodesOut","description":"Shown once, at generation, and never again.\n\nTen single-use codes. They are stored as argon2id hashes, so the platform\ngenuinely cannot show them a second time — which is the property that makes\nthem worth having."},"ReferralCreateIn":{"properties":{"kind":{"$ref":"#/components/schemas/ReferralKind"},"target_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Target Id"},"code":{"anyOf":[{"type":"string","maxLength":32,"minLength":4},{"type":"null"}],"title":"Code"}},"type":"object","required":["kind"],"title":"ReferralCreateIn"},"ReferralKind":{"type":"string","enum":["user","business"],"title":"ReferralKind"},"ReferralOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"referrer_user_id":{"type":"string","format":"uuid","title":"Referrer User Id"},"kind":{"$ref":"#/components/schemas/ReferralKind"},"target_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Target Id"},"code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Code"},"status":{"$ref":"#/components/schemas/ReferralStatus"},"reward_cents":{"type":"integer","title":"Reward Cents"},"converted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Converted At"},"rewarded_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Rewarded At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","referrer_user_id","kind","target_id","code","status","reward_cents","converted_at","rewarded_at","created_at"],"title":"ReferralOut"},"ReferralStatus":{"type":"string","enum":["pending","converted","rewarded","expired"],"title":"ReferralStatus"},"RefreshIn":{"properties":{"refresh_token":{"type":"string","title":"Refresh Token"}},"type":"object","required":["refresh_token"],"title":"RefreshIn"},"RefundComponentsOut":{"properties":{"service_cents":{"type":"integer","title":"Service Cents"},"booking_fee_cents":{"type":"integer","title":"Booking Fee Cents"},"tip_cents":{"type":"integer","title":"Tip Cents"},"tax_cents":{"type":"integer","title":"Tax Cents"}},"type":"object","required":["service_cents","booking_fee_cents","tip_cents","tax_cents"],"title":"RefundComponentsOut","description":"FIN-RULE-005 §8.1: no flat subtraction — every refund names its parts."},"RefundIn":{"properties":{"event":{"type":"string","title":"Event","description":"client_cancel · no_show · professional_cancel · business_cancel · mylook_operational","default":"mylook_operational"},"reason":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Reason"},"idempotency_key":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Idempotency Key"}},"type":"object","title":"RefundIn","description":"Ask for the approved rule for `event` to be applied to a payment.\n\nThe AMOUNT is deliberately absent. A caller that could name a figure would be\na caller that could refund anything; the amount comes from the 2026-08-11\nfreeze via money/policy.py and from the ledger's own record of what is still\ndistributed. What a caller supplies is what HAPPENED."},"RefundOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"payment_id":{"type":"string","format":"uuid","title":"Payment Id"},"appointment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Appointment Id"},"amount_cents":{"type":"integer","title":"Amount Cents"},"components":{"$ref":"#/components/schemas/RefundComponentsOut"},"penalty_cents":{"type":"integer","title":"Penalty Cents"},"policy":{"type":"string","title":"Policy"},"origin":{"type":"string","title":"Origin"},"rule_source":{"type":"string","title":"Rule Source"},"retains_booking_fee":{"type":"boolean","title":"Retains Booking Fee"},"provider_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Ref"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","payment_id","appointment_id","amount_cents","components","penalty_cents","policy","origin","rule_source","retains_booking_fee","provider_ref","created_at"],"title":"RefundOut","description":"One recorded decision about money going back.\n\n`amount_cents` is what the client receives and always equals the components.\n`penalty_cents` is what they do not, and is outside that sum — since the\nowner's decision of 2026-08-12 it is credited to the affected professional as\nCancellation / No-Show Compensation, which is money the client does not get\nback and MyLook does not keep."},"RefundPreviewOut":{"properties":{"payment_id":{"type":"string","format":"uuid","title":"Payment Id"},"policy":{"type":"string","title":"Policy"},"origin":{"type":"string","title":"Origin"},"rule_source":{"type":"string","title":"Rule Source"},"charged":{"$ref":"#/components/schemas/RefundComponentsOut"},"refund":{"$ref":"#/components/schemas/RefundComponentsOut"},"refund_total_cents":{"type":"integer","title":"Refund Total Cents"},"penalty_cents":{"type":"integer","title":"Penalty Cents"},"retains_booking_fee":{"type":"boolean","title":"Retains Booking Fee"},"reschedule_offered":{"type":"boolean","title":"Reschedule Offered"},"tip_rule":{"type":"string","title":"Tip Rule"},"already_refunded":{"type":"boolean","title":"Already Refunded"},"pending":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Pending"},"blocked_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Blocked Reason"}},"type":"object","required":["payment_id","policy","origin","rule_source","charged","refund","refund_total_cents","penalty_cents","retains_booking_fee","reschedule_offered","tip_rule","already_refunded"],"title":"RefundPreviewOut","description":"What cancelling right now would do — the same code path that will run.\n\nThe preview and the outcome cannot disagree, because there is one resolution\nof the rule and both call it."},"RefundRequestDecisionIn":{"properties":{"reason":{"type":"string","maxLength":500,"minLength":1,"title":"Reason"}},"type":"object","required":["reason"],"title":"RefundRequestDecisionIn","description":"'Every approval or rejection records reason, actor, timestamp.' The reason\nis required; the actor and the moment are the platform's to write."},"RefundRequestIn":{"properties":{"category":{"type":"string","title":"Category","description":"business_service · business_product · platform_error · mylook_fee"},"reason":{"type":"string","maxLength":500,"minLength":1,"title":"Reason"}},"type":"object","required":["category","reason"],"title":"RefundRequestIn","description":"HIS DECISION 102 — what the client is asking about, and why. No amount:\nthe amount comes from the approved rule the decision applies."},"RefundRequestOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"payment_id":{"type":"string","format":"uuid","title":"Payment Id"},"requested_by":{"type":"string","format":"uuid","title":"Requested By"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"category":{"type":"string","title":"Category"},"reason":{"type":"string","title":"Reason"},"status":{"type":"string","title":"Status"},"decided_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Decided By"},"decided_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Decided At"},"decision_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Decision Reason"},"refund_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Refund Id"},"blocked_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Blocked Reason"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"amount_cents":{"type":"integer","title":"Amount Cents"},"currency":{"type":"string","title":"Currency"},"customer_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Customer Name"},"decided_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Decided By Name"},"business_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Name"},"appointment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Appointment Id"},"order_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Order Id"},"about":{"type":"string","title":"About"},"reference":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reference"},"refunded_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Refunded Cents"},"provider_ref":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Provider Ref"}},"type":"object","required":["id","payment_id","requested_by","business_id","category","reason","status","decided_by","decided_at","decision_reason","refund_id","blocked_reason","created_at","amount_cents","currency","about"],"title":"RefundRequestOut","description":"One request with its three states visible: the ask (reason, category,\nwho), the decision (decided_by, decided_at, decision_reason) and the money\n(refund_id, refunded_cents, provider_ref — or blocked_reason)."},"RefundRequestsOut":{"properties":{"disputes":{"items":{"$ref":"#/components/schemas/DisputeRowOut"},"type":"array","title":"Disputes"},"held_penalties":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Held Penalties"},"requests":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Requests","default":[]}},"type":"object","required":["disputes","held_penalties"],"title":"RefundRequestsOut"},"RegisterIn":{"properties":{"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email"},"password":{"type":"string","maxLength":128,"minLength":8,"title":"Password"},"full_name":{"type":"string","maxLength":120,"minLength":2,"title":"Full Name"},"phone":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Phone"},"locale":{"type":"string","maxLength":8,"title":"Locale","default":"en"},"date_of_birth":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date Of Birth"},"referral_code":{"anyOf":[{"type":"string","maxLength":32,"minLength":4},{"type":"null"}],"title":"Referral Code"}},"type":"object","required":["password","full_name"],"title":"RegisterIn","description":"HIS CLIENT REGISTRATION v2.0 §3 and his PROFESSIONAL REGISTRATION v1.2 §7.\n\nA PHONE NUMBER **OR** AN E-MAIL, and the phone is the one his screen opens on: \"por defecto\nabrir en Phone number porque mucha gente no usa email\". Either identifies the account; both\nis allowed, because his tabs offer a choice and not a limit.\n\nNOTHING ELSE. His \"LO QUE NO DEBE VIVIR EN EL REGISTRO\" forbids an address, a category, a\nphotograph, a payment method, a professional identity or a business at sign-up, and a field\nthat is not on this model cannot be stored by a caller that sends it anyway."},"RelationshipEndIn":{"properties":{"reason":{"anyOf":[{"type":"string","maxLength":500,"minLength":3},{"type":"null"}],"title":"Reason"}},"type":"object","title":"RelationshipEndIn","description":"His decision 8 — either side may end a relationship. Kept in the history.\n\nHis answer to question 179 (2026-09-14): REQUIRED when a business ends another person's relationship\n(`reason_required`), and kept in the audit log too; a person ending their own may leave it out."},"RelationshipEndOut":{"properties":{"business_id":{"type":"string","format":"uuid","title":"Business Id"},"ended_locations":{"type":"integer","title":"Ended Locations"},"ended_memberships":{"type":"integer","title":"Ended Memberships"},"closed_agreements":{"type":"integer","title":"Closed Agreements"},"future_appointments":{"type":"integer","title":"Future Appointments"}},"type":"object","required":["business_id","ended_locations","ended_memberships","closed_agreements","future_appointments"],"title":"RelationshipEndOut","description":"What ending closed, so neither side is left guessing.\n\n`future_appointments` is COUNTED, never touched: \"Existing/future appointments are not\nsilently moved or cancelled\" (his decision 8). The business decides what to do with them,\nas it does for a closing location (his decision 145)."},"RentCycleOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"agreement_id":{"type":"string","format":"uuid","title":"Agreement Id"},"period_start":{"type":"string","format":"date","title":"Period Start"},"period_end":{"type":"string","format":"date","title":"Period End"},"due_cents":{"type":"integer","title":"Due Cents"},"collected_cents":{"type":"integer","title":"Collected Cents"},"remaining_cents":{"type":"integer","title":"Remaining Cents"},"status":{"type":"string","title":"Status"},"closed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Closed At"}},"type":"object","required":["id","agreement_id","period_start","period_end","due_cents","collected_cents","remaining_cents","status","closed_at"],"title":"RentCycleOut","description":"The rent, and nothing else. No sales, no clients, no tips — that is the client's\nfinancial-privacy rule for a chair-rent professional, not a display choice."},"ReorderIn":{"properties":{"item_ids":{"items":{"type":"string","format":"uuid"},"type":"array","maxItems":200,"minItems":1,"title":"Item Ids"}},"type":"object","required":["item_ids"],"title":"ReorderIn"},"RequestInfoIn":{"properties":{"to":{"type":"string","enum":["customer","business"],"title":"To"},"message":{"type":"string","maxLength":4000,"minLength":3,"title":"Message"}},"type":"object","required":["to","message"],"title":"RequestInfoIn"},"RescheduleIn":{"properties":{"starts_at":{"type":"string","format":"date-time","title":"Starts At"}},"type":"object","required":["starts_at"],"title":"RescheduleIn","description":"Where the client wants to move to.\n\nOnly a time. Not a professional, not a service, not a price — moving an\nappointment must not become a way to change what was agreed and pay the old\namount for it. Everything else is carried across from the booking that\nalready exists."},"ResetPasswordIn":{"properties":{"token":{"type":"string","maxLength":200,"minLength":16,"title":"Token"},"new_password":{"type":"string","maxLength":200,"minLength":10,"title":"New Password"}},"type":"object","required":["token","new_password"],"title":"ResetPasswordIn"},"ResolveAlertIn":{"properties":{"status":{"type":"string","enum":["actioned","dismissed"],"title":"Status"},"resolution":{"type":"string","maxLength":2000,"minLength":3,"title":"Resolution"}},"type":"object","required":["status","resolution"],"title":"ResolveAlertIn","description":"'actioned' when something was done, 'dismissed' when it was nothing —\nand the difference is recorded, because \"we looked and it was fine\" is an\nanswer worth being able to prove later."},"ResolveIn":{"properties":{"action":{"type":"string","enum":["approved","rejected","closed"],"title":"Action"},"note":{"type":"string","maxLength":4000,"minLength":3,"title":"Note"},"unpublish_review":{"type":"boolean","title":"Unpublish Review","default":false}},"type":"object","required":["action","note"],"title":"ResolveIn"},"ReviewAttributeOut":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"sort_order":{"type":"integer","title":"Sort Order"}},"type":"object","required":["key","label","sort_order"],"title":"ReviewAttributeOut","description":"One of the chips his \"What did you like?\" screen draws."},"ReviewCreateIn":{"properties":{"appointment_id":{"type":"string","format":"uuid","title":"Appointment Id"},"rating":{"type":"integer","maximum":5.0,"minimum":1.0,"title":"Rating"},"comment":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"title":"Comment"},"service_quality":{"anyOf":[{"type":"integer","maximum":5.0,"minimum":1.0},{"type":"null"}],"title":"Service Quality"},"cleanliness":{"anyOf":[{"type":"integer","maximum":5.0,"minimum":1.0},{"type":"null"}],"title":"Cleanliness"},"punctuality":{"anyOf":[{"type":"integer","maximum":5.0,"minimum":1.0},{"type":"null"}],"title":"Punctuality"},"photo_keys":{"items":{"type":"string"},"type":"array","maxItems":10,"title":"Photo Keys"},"attributes":{"items":{"type":"string"},"type":"array","maxItems":20,"title":"Attributes"},"media_consent":{"type":"boolean","title":"Media Consent","default":false}},"type":"object","required":["appointment_id","rating"],"title":"ReviewCreateIn","description":"The appointment decides everything else: which business, which location and\nwhich professional are read from it, never sent by the client."},"ReviewEditIn":{"properties":{"rating":{"anyOf":[{"type":"integer","maximum":5.0,"minimum":1.0},{"type":"null"}],"title":"Rating"},"comment":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"title":"Comment"}},"type":"object","title":"ReviewEditIn","description":"The author correcting what they wrote — his decision 31.\n\nBoth optional: somebody fixing a typo does not restate their rating, and\nsomebody who changed their mind about the rating does not have to retype\ntheir comment."},"ReviewInboxItemOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"appointment_id":{"type":"string","format":"uuid","title":"Appointment Id"},"client_user_id":{"type":"string","format":"uuid","title":"Client User Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"professional_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Professional Id"},"rating":{"type":"integer","title":"Rating"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment"},"service_quality":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Service Quality"},"cleanliness":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cleanliness"},"punctuality":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Punctuality"},"photo_keys":{"items":{"type":"string"},"type":"array","title":"Photo Keys","default":[]},"is_published":{"type":"boolean","title":"Is Published"},"state":{"type":"string","title":"State","default":"published"},"state_changed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"State Changed At"},"edited_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Edited At"},"removal_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Removal Reason"},"attributes":{"items":{"type":"string"},"type":"array","title":"Attributes","default":[]},"media_consent":{"type":"boolean","title":"Media Consent","default":false},"media_consent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Media Consent At"},"media_consent_revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Media Consent Revoked At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"response":{"anyOf":[{"$ref":"#/components/schemas/ReviewResponseOut"},{"type":"null"}]},"client_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Name"},"service_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Name"},"professional_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Professional Name"},"needs_reply":{"type":"boolean","title":"Needs Reply","default":false},"is_new":{"type":"boolean","title":"Is New","default":false}},"type":"object","required":["id","appointment_id","client_user_id","business_id","branch_id","professional_id","rating","comment","service_quality","cleanliness","punctuality","is_published","created_at"],"title":"ReviewInboxItemOut","description":"A review as the BUSINESS reads it — with the names the public list must not\ncarry: who wrote it, what service it was, which professional gave it."},"ReviewMetricOut":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"unit":{"type":"string","title":"Unit"},"definition":{"type":"string","title":"Definition"},"lineage":{"type":"string","title":"Lineage"},"value":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Value"},"change":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Change"},"series":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Series","default":[]},"sample_size":{"type":"integer","title":"Sample Size","default":0},"numerator":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Numerator"},"denominator":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Denominator"}},"type":"object","required":["key","label","unit","definition","lineage"],"title":"ReviewMetricOut","description":"One governed metric — his decision 34.\n\nTHE DEFINITION AND THE LINEAGE ARE PART OF THE PAYLOAD, not documentation\nsomewhere else. \"Analytics records definitions and lineage; no screen\nrecalculates them differently\" is only true if a screen cannot show the\nnumber without also being able to show what it counts and where it came\nfrom. So they travel together, and a figure quoted without them is one\nsomebody made up."},"ReviewMetricsOut":{"properties":{"window_months":{"type":"integer","title":"Window Months"},"window_starts_at":{"type":"string","format":"date-time","title":"Window Starts At"},"computed_at":{"type":"string","format":"date-time","title":"Computed At"},"metrics":{"items":{"$ref":"#/components/schemas/ReviewMetricOut"},"type":"array","title":"Metrics"}},"type":"object","required":["window_months","window_starts_at","computed_at","metrics"],"title":"ReviewMetricsOut"},"ReviewOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"appointment_id":{"type":"string","format":"uuid","title":"Appointment Id"},"client_user_id":{"type":"string","format":"uuid","title":"Client User Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"professional_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Professional Id"},"rating":{"type":"integer","title":"Rating"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment"},"service_quality":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Service Quality"},"cleanliness":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Cleanliness"},"punctuality":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Punctuality"},"photo_keys":{"items":{"type":"string"},"type":"array","title":"Photo Keys","default":[]},"is_published":{"type":"boolean","title":"Is Published"},"state":{"type":"string","title":"State","default":"published"},"state_changed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"State Changed At"},"edited_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Edited At"},"removal_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Removal Reason"},"attributes":{"items":{"type":"string"},"type":"array","title":"Attributes","default":[]},"media_consent":{"type":"boolean","title":"Media Consent","default":false},"media_consent_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Media Consent At"},"media_consent_revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Media Consent Revoked At"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"response":{"anyOf":[{"$ref":"#/components/schemas/ReviewResponseOut"},{"type":"null"}]}},"type":"object","required":["id","appointment_id","client_user_id","business_id","branch_id","professional_id","rating","comment","service_quality","cleanliness","punctuality","is_published","created_at"],"title":"ReviewOut"},"ReviewReportIn":{"properties":{"reason":{"type":"string","enum":["spam","offensive","not_about_this_visit","personal_information","conflict_of_interest","other"],"title":"Reason"},"detail":{"anyOf":[{"type":"string","maxLength":1000},{"type":"null"}],"title":"Detail"}},"type":"object","required":["reason"],"title":"ReviewReportIn","description":"A claim that a review breaks a rule — not a complaint about a rating.\n\nThe vocabulary is deliberately short: a long list makes people pick the\nnearest word rather than the true one."},"ReviewReportOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"review_id":{"type":"string","format":"uuid","title":"Review Id"},"reason":{"type":"string","title":"Reason"},"status":{"type":"string","title":"Status"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","review_id","reason","status","created_at"],"title":"ReviewReportOut"},"ReviewRequestIn":{"properties":{"appointment_id":{"type":"string","format":"uuid","title":"Appointment Id"},"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id"}},"type":"object","required":["appointment_id"],"title":"ReviewRequestIn"},"ReviewRequestOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"appointment_id":{"type":"string","format":"uuid","title":"Appointment Id"},"client_user_id":{"type":"string","format":"uuid","title":"Client User Id"},"template_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Template Id"},"message":{"type":"string","title":"Message"},"sent_at":{"type":"string","format":"date-time","title":"Sent At"},"review_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Review Id"},"reviewed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Reviewed At"}},"type":"object","required":["id","business_id","appointment_id","client_user_id","template_id","message","sent_at"],"title":"ReviewRequestOut"},"ReviewRequestTemplateIn":{"properties":{"name":{"type":"string","maxLength":120,"minLength":1,"title":"Name"},"body":{"type":"string","maxLength":1000,"minLength":1,"title":"Body"},"is_default":{"type":"boolean","title":"Is Default","default":false}},"type":"object","required":["name","body"],"title":"ReviewRequestTemplateIn"},"ReviewRequestTemplateOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"name":{"type":"string","title":"Name"},"body":{"type":"string","title":"Body"},"is_default":{"type":"boolean","title":"Is Default"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","business_id","name","body","is_default","created_at"],"title":"ReviewRequestTemplateOut"},"ReviewRequestTemplateUpdateIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":120,"minLength":1},{"type":"null"}],"title":"Name"},"body":{"anyOf":[{"type":"string","maxLength":1000,"minLength":1},{"type":"null"}],"title":"Body"},"is_default":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Default"}},"type":"object","title":"ReviewRequestTemplateUpdateIn","description":"Every field optional — `exclude_unset` decides what was actually sent.\n\nLearned the hard way on PUT /social, where a payload naming one platform\nwiped the other four because unsent fields arrived as None and None read as\n\"clear it\"."},"ReviewResponseIn":{"properties":{"body":{"type":"string","maxLength":4000,"minLength":1,"title":"Body"}},"type":"object","required":["body"],"title":"ReviewResponseIn"},"ReviewResponseOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"review_id":{"type":"string","format":"uuid","title":"Review Id"},"author_id":{"type":"string","format":"uuid","title":"Author Id"},"body":{"type":"string","title":"Body"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","review_id","author_id","body","created_at"],"title":"ReviewResponseOut"},"RolesIn":{"properties":{"roles":{"items":{"type":"string","enum":["client","professional","business"]},"type":"array","minItems":1,"title":"Roles"}},"type":"object","required":["roles"],"title":"RolesIn","description":"His ONB-004. A SET, never a value.\n\n\"Permitir MULTI-SELECT. El usuario puede seleccionar Client, Professional,\n Business Owner simultáneamente.\""},"RolesSummaryOut":{"properties":{"active":{"type":"integer","title":"Active"},"by_role":{"additionalProperties":{"type":"integer"},"type":"object","title":"By Role"},"roles":{"items":{"type":"string"},"type":"array","title":"Roles"},"recent":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Recent"}},"type":"object","required":["active","by_role","roles","recent"],"title":"RolesSummaryOut"},"RoutingIn":{"properties":{"role":{"type":"string","title":"Role"}},"type":"object","required":["role"],"title":"RoutingIn"},"RunningLateIn":{"properties":{"estimated_delay_minutes":{"type":"integer","maximum":240.0,"minimum":1.0,"title":"Estimated Delay Minutes"},"message":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Message"}},"type":"object","required":["estimated_delay_minutes"],"title":"RunningLateIn","description":"HIS §24: the client's own \"I'm running late\", from their own app.\n\nThe delay is required — \"RUNNING LATE\" with no number is a sentence the professional cannot\nact on — and bounded by the table at 240 minutes, past which it is not a late arrival."},"SearchGroupOut":{"properties":{"kind":{"type":"string","title":"Kind"},"label":{"type":"string","title":"Label"},"href":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Href"},"items":{"items":{"$ref":"#/components/schemas/SearchItemOut"},"type":"array","title":"Items"}},"type":"object","required":["kind","label","href","items"],"title":"SearchGroupOut"},"SearchItemOut":{"properties":{"id":{"type":"string","title":"Id"},"title":{"type":"string","title":"Title"},"subtitle":{"type":"string","title":"Subtitle"},"status":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Status"}},"type":"object","required":["id","title","subtitle","status"],"title":"SearchItemOut"},"SearchOut":{"properties":{"query":{"type":"string","title":"Query"},"groups":{"items":{"$ref":"#/components/schemas/SearchGroupOut"},"type":"array","title":"Groups"},"total":{"type":"integer","title":"Total"},"not_searchable":{"items":{"type":"string"},"type":"array","title":"Not Searchable"}},"type":"object","required":["query","groups","total","not_searchable"],"title":"SearchOut"},"SecuritySummaryOut":{"properties":{"staff_2fa_mode":{"type":"string","title":"Staff 2Fa Mode"},"staff_2fa_enforced":{"type":"boolean","title":"Staff 2Fa Enforced"},"production":{"type":"boolean","title":"Production"},"protected":{"type":"integer","title":"Protected"},"unprotected":{"type":"integer","title":"Unprotected"}},"type":"object","required":["staff_2fa_mode","staff_2fa_enforced","production","protected","unprotected"],"title":"SecuritySummaryOut"},"SellableServiceOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"price_cents":{"type":"integer","title":"Price Cents"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"}},"type":"object","required":["id","name","duration_minutes","price_cents","branch_id"],"title":"SellableServiceOut","description":"One service the caller may book at that location — his §14's picker, and his suggested\nduration comes from this length rather than from a list of round numbers."},"ServiceCreateIn":{"properties":{"name":{"type":"string","maxLength":120,"minLength":2,"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Category Id"},"duration_minutes":{"type":"integer","maximum":600.0,"exclusiveMinimum":0.0,"title":"Duration Minutes"},"price_cents":{"type":"integer","minimum":0.0,"title":"Price Cents"},"deposit_cents":{"type":"integer","minimum":0.0,"title":"Deposit Cents","default":0},"buffer_minutes":{"type":"integer","maximum":120.0,"minimum":0.0,"title":"Buffer Minutes","default":0},"slot_interval_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Slot Interval Minutes","description":"5, 10, 15, 20, 30, 45 or 60 — or null to follow the location. This is how far apart start times are offered, NOT how long the service takes."},"options":{"items":{"$ref":"#/components/schemas/ServiceOptionIn"},"type":"array","title":"Options"}},"type":"object","required":["name","duration_minutes","price_cents"],"title":"ServiceCreateIn"},"ServiceOptionIn":{"properties":{"name":{"type":"string","maxLength":80,"minLength":1,"title":"Name"},"duration_delta_minutes":{"type":"integer","title":"Duration Delta Minutes","default":0},"price_delta_cents":{"type":"integer","title":"Price Delta Cents","default":0}},"type":"object","required":["name"],"title":"ServiceOptionIn"},"ServiceOptionOut":{"properties":{"name":{"type":"string","maxLength":80,"minLength":1,"title":"Name"},"duration_delta_minutes":{"type":"integer","title":"Duration Delta Minutes","default":0},"price_delta_cents":{"type":"integer","title":"Price Delta Cents","default":0},"id":{"type":"string","format":"uuid","title":"Id"},"is_active":{"type":"boolean","title":"Is Active"}},"type":"object","required":["name","id","is_active"],"title":"ServiceOptionOut"},"ServiceOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Category Id"},"name":{"type":"string","title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"price_cents":{"type":"integer","title":"Price Cents"},"deposit_cents":{"type":"integer","title":"Deposit Cents"},"buffer_minutes":{"type":"integer","title":"Buffer Minutes"},"slot_interval_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Slot Interval Minutes"},"is_active":{"type":"boolean","title":"Is Active"},"options":{"items":{"$ref":"#/components/schemas/ServiceOptionOut"},"type":"array","title":"Options","default":[]}},"type":"object","required":["id","business_id","category_id","name","description","duration_minutes","price_cents","deposit_cents","buffer_minutes","is_active"],"title":"ServiceOut"},"ServiceUpdateIn":{"properties":{"name":{"anyOf":[{"type":"string","maxLength":120,"minLength":2},{"type":"null"}],"title":"Name"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"},"category_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Category Id"},"duration_minutes":{"anyOf":[{"type":"integer","maximum":600.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Duration Minutes"},"price_cents":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Price Cents"},"deposit_cents":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Deposit Cents"},"buffer_minutes":{"anyOf":[{"type":"integer","maximum":120.0,"minimum":0.0},{"type":"null"}],"title":"Buffer Minutes"},"slot_interval_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Slot Interval Minutes","description":"5, 10, 15, 20, 30, 45 or 60 — or null to follow the location. This is how far apart start times are offered, NOT how long the service takes."},"is_active":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Is Active"}},"type":"object","title":"ServiceUpdateIn"},"SessionOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"device_label":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Device Label"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"}},"type":"object","required":["id","device_label","created_at","expires_at"],"title":"SessionOut"},"SetupStageOut":{"properties":{"key":{"type":"string","title":"Key"},"label":{"type":"string","title":"Label"},"hint":{"type":"string","title":"Hint"},"route":{"type":"string","title":"Route"},"done":{"type":"boolean","title":"Done"},"detail":{"type":"string","title":"Detail"}},"type":"object","required":["key","label","hint","route","done","detail"],"title":"SetupStageOut","description":"One of his eight, with the reason it is or is not done."},"SetupStateOut":{"properties":{"business_id":{"type":"string","format":"uuid","title":"Business Id"},"status":{"type":"string","title":"Status"},"stages":{"items":{"$ref":"#/components/schemas/SetupStageOut"},"type":"array","title":"Stages"},"done":{"type":"integer","title":"Done"},"total":{"type":"integer","title":"Total"},"can_publish":{"type":"boolean","title":"Can Publish"},"blocking":{"items":{"type":"string"},"type":"array","title":"Blocking"}},"type":"object","required":["business_id","status","stages","done","total","can_publish","blocking"],"title":"SetupStateOut","description":"His decision 11 — Business Setup, computed from real data."},"ShopConversationOpenIn":{"properties":{"client_user_id":{"type":"string","format":"uuid","title":"Client User Id"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"subject":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Subject"},"appointment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Appointment Id"}},"type":"object","required":["client_user_id"],"title":"ShopConversationOpenIn","description":"A shop writing first — owner question 66.\n\n`branch_id` may be left out by a single-location shop, or by a member who\nbelongs to one: the same convention stock movements and the clients list use."},"ShopOrderOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"reference":{"type":"string","title":"Reference"},"status":{"type":"string","title":"Status"},"fulfillment":{"type":"string","title":"Fulfillment"},"currency":{"type":"string","title":"Currency"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"business_name":{"type":"string","title":"Business Name"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"branch_name":{"type":"string","title":"Branch Name"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"items":{"items":{"$ref":"#/components/schemas/OrderItemOut"},"type":"array","title":"Items"},"subtotal_cents":{"type":"integer","title":"Subtotal Cents"},"discount_cents":{"type":"integer","title":"Discount Cents","default":0},"membership_plan_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Membership Plan Id"},"fee_cents":{"type":"integer","title":"Fee Cents"},"tax_cents":{"type":"integer","title":"Tax Cents"},"total_cents":{"type":"integer","title":"Total Cents"},"payment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Payment Id"},"client_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Note"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"paid_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Paid At"},"accepted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Accepted At"},"preparing_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Preparing At"},"ready_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ready At"},"completed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Completed At"},"cancelled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Cancelled At"},"cancelled_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Cancelled Reason"},"refunded_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Refunded At"},"refunded_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Refunded Cents"},"pickup_window_starts_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Pickup Window Starts At"},"pickup_window_ends_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Pickup Window Ends At"},"receipt_lines":{"anyOf":[{"items":{"$ref":"#/components/schemas/OrderReceiptLineOut"},"type":"array"},{"type":"null"}],"title":"Receipt Lines"},"receipt_total_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Receipt Total Cents"},"client_user_id":{"type":"string","format":"uuid","title":"Client User Id"},"client_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Name"}},"type":"object","required":["id","reference","status","fulfillment","currency","business_id","business_name","branch_id","branch_name","city","state","items","subtotal_cents","fee_cents","tax_cents","total_cents","payment_id","client_note","created_at","paid_at","ready_at","completed_at","cancelled_at","cancelled_reason","client_user_id"],"title":"ShopOrderOut","description":"An order as the SHOP reads it: the buyer's id and name ride along, so the\ncounter knows who is collecting. The buyer's own read never carries these —\nthey are about them."},"SkillIn":{"properties":{"service_id":{"type":"string","format":"uuid","title":"Service Id"},"price_cents":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Price Cents"},"duration_minutes":{"anyOf":[{"type":"integer","maximum":600.0,"exclusiveMinimum":0.0},{"type":"null"}],"title":"Duration Minutes"}},"type":"object","required":["service_id"],"title":"SkillIn","description":"What a professional can actually perform. Optional per-person overrides."},"SkillOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"professional_id":{"type":"string","format":"uuid","title":"Professional Id"},"service_id":{"type":"string","format":"uuid","title":"Service Id"},"price_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price Cents"},"duration_minutes":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Duration Minutes"},"is_active":{"type":"boolean","title":"Is Active"}},"type":"object","required":["id","professional_id","service_id","price_cents","duration_minutes","is_active"],"title":"SkillOut"},"SkillsIn":{"properties":{"categories":{"items":{"type":"string","enum":["booking","payments","orders","accounts","safety_fraud","reviews"]},"type":"array","maxItems":6,"title":"Categories"}},"type":"object","title":"SkillsIn","description":"The queues an agent works — the drawn categories, nothing else."},"SlotOut":{"properties":{"professional_id":{"type":"string","format":"uuid","title":"Professional Id"},"starts_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Starts At"},"ends_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ends At"},"duration_minutes":{"type":"integer","title":"Duration Minutes"},"price_cents":{"type":"integer","title":"Price Cents"}},"type":"object","required":["professional_id","starts_at","ends_at","duration_minutes","price_cents"],"title":"SlotOut","description":"A bookable slot. It carries its professional, because a search without a\nprofessional returns slots from everyone at the branch who has the skill."},"SocialLinkOut":{"properties":{"platform":{"type":"string","enum":["instagram","tiktok","facebook","youtube","website"],"title":"Platform"},"handle":{"type":"string","title":"Handle"}},"type":"object","required":["platform","handle"],"title":"SocialLinkOut"},"SocialLinksIn":{"properties":{"instagram":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Instagram"},"tiktok":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Tiktok"},"facebook":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Facebook"},"youtube":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Youtube"},"website":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Website"}},"type":"object","title":"SocialLinksIn","description":"His five, all optional, all skippable.\n\nA platform sent as null or \"\" is REMOVED — that is how somebody disconnects\none, in the same gesture that added it, with no second endpoint."},"SpecialtyOut":{"properties":{"slug":{"type":"string","title":"Slug"},"name":{"type":"string","title":"Name"},"note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Note"},"parent_slug":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parent Slug"},"parent_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Parent Name"}},"type":"object","required":["slug","name"],"title":"SpecialtyOut","description":"One entry of his MyLook taxonomy, plus the professional's own line about\nit. `note` is the \"complemento descriptivo\" — never the primary source.\n\nHIS DECISION 150 made the taxonomy a TREE. `parent_slug` is the group this\nentry sits in, and is null on a group itself — a group is selectable in its\nown right, because somebody who does every kind of nail work says Nails\nrather than ticking five children."},"StaffActionIn":{"properties":{"reason":{"type":"string","maxLength":500,"minLength":3,"title":"Reason","description":"Why this decision was taken. Kept forever, against the staff member who took it."}},"type":"object","required":["reason"],"title":"StaffActionIn","description":"What every platform-staff decision carries.\n\n`reason` is REQUIRED, and a blank one is refused at the edge as well as by\nthe database. The client's complaint about the previous system's\n`membership_tier` was not that the field existed — it was that standing\ncould be awarded with nothing recording where it came from. A verified\nbusiness whose verification nobody can explain reproduces exactly that,\nwith a boolean instead of a string."},"StaffBookingIn":{"properties":{"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"professional_id":{"type":"string","format":"uuid","title":"Professional Id"},"service_id":{"type":"string","format":"uuid","title":"Service Id"},"starts_at":{"type":"string","format":"date-time","title":"Starts At"},"client_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Client User Id"},"guest_name":{"anyOf":[{"type":"string","maxLength":120,"minLength":2},{"type":"null"}],"title":"Guest Name"},"guest_phone":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Guest Phone"},"payment_channel":{"type":"string","enum":["mylook","at_the_shop"],"title":"Payment Channel","default":"at_the_shop"},"source":{"type":"string","enum":["walk_in","phone"],"title":"Source","default":"walk_in"},"client_note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Client Note"}},"type":"object","required":["branch_id","professional_id","service_id","starts_at"],"title":"StaffBookingIn","description":"The SHOP putting somebody in the book — his decision 12.\n\n\"Authorised owner, manager or front desk may create appointments for clients\n and register walk-ins. They must identify an existing client or a new/guest\n client, and a payment method.\"\n\nIDENTIFY ONE OR THE OTHER. `client_user_id` for somebody with a MyLook\naccount — the appointment is theirs, appears in their app and they pay for\nit. `guest_name` for somebody who walked in off the street. Sending neither\nis refused; sending both is refused too, because a booking with two clients\nis a booking nobody owns.\n\nPAYMENT. `at_the_shop` is the only channel open to a guest: there is no\naccount to charge and staff must never handle a card number. A client with\nan account may be booked either way — through MyLook, which is an ordinary\nbooking they pay in their own app, or at the counter."},"StaffCaseOpenIn":{"properties":{"category":{"anyOf":[{"type":"string","enum":["booking","payments","orders","accounts","safety_fraud","reviews"]},{"type":"null"}],"title":"Category"},"subtype":{"type":"string","maxLength":80,"minLength":2,"title":"Subtype"},"subject":{"type":"string","maxLength":160,"minLength":3,"title":"Subject"},"description":{"type":"string","maxLength":4000,"minLength":10,"title":"Description"},"appointment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Appointment Id"},"order_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Order Id"},"payment_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Payment Id"},"review_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Review Id"},"subscription_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Subscription Id"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"customer_user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Customer User Id"}},"type":"object","required":["subtype","subject","description"],"title":"StaffCaseOpenIn","description":"His \"Create Case — Start a new case\" on the Deep Operations Hub: support\nopens a case on a customer's behalf (a phone call, a walk-in report). The\nparties are still read from the thing the case is about when one is named;\notherwise the customer and/or business given here."},"StaffGrantIn":{"properties":{"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email"},"role":{"type":"string","enum":["admin","support","finance","moderator","regional_manager"],"title":"Role"},"reason":{"type":"string","maxLength":2000,"minLength":3,"title":"Reason"},"scopes":{"items":{"additionalProperties":true,"type":"object"},"type":"array","maxItems":200,"title":"Scopes"}},"type":"object","required":["role","reason"],"title":"StaffGrantIn","description":"Who — by id or by e-mail — which of the platform's four roles, and why.\nThe reason goes on the audit trail verbatim."},"StaffOut":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id"},"full_name":{"type":"string","title":"Full Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"status":{"type":"string","title":"Status"},"role":{"type":"string","title":"Role"},"granted_at":{"type":"string","format":"date-time","title":"Granted At"},"granted_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Granted By"},"granted_by_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Granted By Name"},"revoked_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Revoked At"},"scopes":{"items":{"additionalProperties":true,"type":"object"},"type":"array","title":"Scopes","default":[]},"active":{"type":"boolean","title":"Active"}},"type":"object","required":["user_id","full_name","email","status","role","granted_at","granted_by","granted_by_name","revoked_at","active"],"title":"StaffOut","description":"One person holding (or having held) a platform role."},"StaffRevokeIn":{"properties":{"reason":{"type":"string","maxLength":2000,"minLength":3,"title":"Reason"}},"type":"object","required":["reason"],"title":"StaffRevokeIn"},"StaffTwoFactorOut":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id"},"full_name":{"type":"string","title":"Full Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"platform_role":{"type":"string","title":"Platform Role"},"enabled":{"type":"boolean","title":"Enabled"},"pending":{"type":"boolean","title":"Pending"},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Confirmed At"},"recovery_codes_remaining":{"type":"integer","title":"Recovery Codes Remaining"},"required":{"type":"boolean","title":"Required"}},"type":"object","required":["user_id","full_name","email","platform_role","enabled","pending","recovery_codes_remaining","required"],"title":"StaffTwoFactorOut","description":"One row of the compliance list: who is protected, and who is not."},"StatusChangeIn":{"properties":{"to_status":{"type":"string","enum":["confirmed","checked_in","in_progress","completed","no_show"],"title":"To Status"},"note":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Note"}},"type":"object","required":["to_status"],"title":"StatusChangeIn"},"SubscribeIn":{"properties":{"plan_id":{"type":"string","format":"uuid","title":"Plan Id"},"card_number":{"anyOf":[{"type":"string","maxLength":25},{"type":"null"}],"title":"Card Number"}},"type":"object","required":["plan_id"],"title":"SubscribeIn"},"SubscriptionOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"plan_id":{"type":"string","format":"uuid","title":"Plan Id"},"status":{"type":"string","title":"Status"},"current_period_start":{"type":"string","format":"date-time","title":"Current Period Start"},"current_period_end":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Current Period End"},"cancelled_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Cancelled At"},"plan":{"$ref":"#/components/schemas/PlanOut"}},"type":"object","required":["id","plan_id","status","current_period_start","current_period_end","cancelled_at","plan"],"title":"SubscriptionOut"},"SuspendIn":{"properties":{"reason":{"type":"string","maxLength":2000,"minLength":3,"title":"Reason"},"public_reason":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Public Reason"}},"type":"object","required":["reason"],"title":"SuspendIn","description":"Never optional. A suspension with no reason cannot be reviewed, appealed\nor explained to the person it is about."},"SuspensionEventOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"action":{"type":"string","title":"Action"},"reason":{"type":"string","title":"Reason"},"public_reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Public Reason"},"actor_id":{"type":"string","format":"uuid","title":"Actor Id"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","action","reason","actor_id","created_at"],"title":"SuspensionEventOut"},"SuspensionOut":{"properties":{"user_id":{"type":"string","format":"uuid","title":"User Id"},"status":{"type":"string","title":"Status"},"sessions_ended":{"type":"integer","title":"Sessions Ended"},"touches":{"additionalProperties":true,"type":"object","title":"Touches"}},"type":"object","required":["user_id","status","sessions_ended","touches"],"title":"SuspensionOut"},"TeamInvitationIn":{"properties":{"user_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"User Id"},"email":{"anyOf":[{"type":"string","format":"email"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Phone"},"role":{"type":"string","pattern":"^(owner|manager|professional|front_desk|assistant)$","title":"Role"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"permissions":{"additionalProperties":{"type":"boolean"},"type":"object","title":"Permissions"},"reason":{"anyOf":[{"type":"string","maxLength":500,"minLength":3},{"type":"null"}],"title":"Reason"},"title":{"anyOf":[{"type":"string","maxLength":80},{"type":"null"}],"title":"Title"}},"type":"object","required":["role"],"title":"TeamInvitationIn","description":"Ask a person to join the team — CR-SEC-2026-09-14-03.\n\nThe same ways of naming a person as before (his decision 25), and the same scope rules. A\nphone number finds only an account whose number is VERIFIED (his decision 9: \"Phone may be\nused through a verified flow\"). A professional joins at a location, so `branch_id` is required\nfor that role; `title` is their title at this business (his decision 7)."},"TeamInvitationOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"business_id":{"type":"string","format":"uuid","title":"Business Id"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"role":{"type":"string","title":"Role"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"permissions":{"additionalProperties":true,"type":"object","title":"Permissions","default":{}},"invited_via":{"type":"string","title":"Invited Via"},"invited_contact":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Invited Contact"},"status":{"type":"string","title":"Status"},"invited_by":{"type":"string","format":"uuid","title":"Invited By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"expires_at":{"type":"string","format":"date-time","title":"Expires At"},"last_sent_at":{"type":"string","format":"date-time","title":"Last Sent At"},"send_count":{"type":"integer","title":"Send Count"},"responded_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Responded At"},"new_invitation_requested_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"New Invitation Requested At"},"resend_available_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Resend Available At"},"reinvite_available_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Reinvite Available At"}},"type":"object","required":["id","business_id","branch_id","role","invited_via","status","invited_by","created_at","expires_at","last_sent_at","send_count"],"title":"TeamInvitationOut","description":"An invitation as the BUSINESS sees it.\n\nBefore an answer the business sees what it typed (`invited_contact`) and nothing about the\naccount behind it: no id, no name. After an acceptance the person is on the team and appears\nin the members list. A decline carries no reason, because none is stored (his decision 10).\n`status` reads `expired` as soon as the seven days have run out, even before the worker's\nnext pass records it."},"TeamPulseOut":{"properties":{"date":{"type":"string","format":"date","title":"Date"},"available_today":{"$ref":"#/components/schemas/PulseFigureOut"},"busy_now":{"$ref":"#/components/schemas/PulseFigureOut"},"capacity":{"$ref":"#/components/schemas/PulseFigureOut"},"next_shift":{"$ref":"#/components/schemas/PulseFigureOut"},"weekly_coverage":{"$ref":"#/components/schemas/PulseFigureOut"}},"type":"object","required":["date","available_today","busy_now","capacity","next_shift","weekly_coverage"],"title":"TeamPulseOut","description":"His decision 26 — the five numbers on the Team screen."},"TemplateIn":{"properties":{"title":{"type":"string","maxLength":120,"minLength":2,"title":"Title"},"body":{"type":"string","maxLength":4000,"minLength":2,"title":"Body"}},"type":"object","required":["title","body"],"title":"TemplateIn"},"TemplateOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"title":{"type":"string","title":"Title"},"body":{"type":"string","title":"Body"},"is_active":{"type":"boolean","title":"Is Active"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","title","body","is_active","created_at"],"title":"TemplateOut"},"TimeBlockIn":{"properties":{"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"professional_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Professional Id"},"starts_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Starts At"},"ends_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ends At"},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End Date"},"start_time":{"anyOf":[{"type":"string","format":"time"},{"type":"null"}],"title":"Start Time"},"end_time":{"anyOf":[{"type":"string","format":"time"},{"type":"null"}],"title":"End Time"},"reason":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Reason"},"repeats":{"type":"string","enum":["does_not_repeat","daily","weekly"],"title":"Repeats","default":"does_not_repeat"},"type_code":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Type Code"},"all_day":{"type":"boolean","title":"All Day","default":false},"private_note":{"anyOf":[{"type":"string","maxLength":150},{"type":"null"}],"title":"Private Note"}},"type":"object","required":["branch_id"],"title":"TimeBlockIn","description":"A block, as SCH-06 and his APPOINTMENTS screen 8 both save one.\n\nTWO WAYS TO SAY WHEN, because his two screens type it differently. SCH-06 picks a date and a\ntime range and sends instants. His screen 8 picks a start DATE and an end DATE with an \"All\nDay\" switch — \"del 20 al 27 de septiembre\" — and the conversion into instants belongs to the\nplatform: the branch's timezone is its knowledge, and a phone that did the arithmetic would\ndo it in whatever zone the phone is in."},"TimeBlockOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"professional_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Professional Id"},"starts_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Starts At"},"ends_at":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ends At"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"type_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Type Code"},"all_day":{"type":"boolean","title":"All Day","default":false},"private_note":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Private Note"},"repeats":{"type":"string","title":"Repeats","default":"does_not_repeat"}},"type":"object","required":["id","branch_id","professional_id","starts_at","ends_at","reason"],"title":"TimeBlockOut"},"TimeBlockPatch":{"properties":{"starts_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Starts At"},"ends_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Ends At"},"start_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Start Date"},"end_date":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"End Date"},"start_time":{"anyOf":[{"type":"string","format":"time"},{"type":"null"}],"title":"Start Time"},"end_time":{"anyOf":[{"type":"string","format":"time"},{"type":"null"}],"title":"End Time"},"reason":{"anyOf":[{"type":"string","maxLength":300},{"type":"null"}],"title":"Reason"},"type_code":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Type Code"},"all_day":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"All Day"},"private_note":{"anyOf":[{"type":"string","maxLength":150},{"type":"null"}],"title":"Private Note"},"repeats":{"anyOf":[{"type":"string","enum":["does_not_repeat","daily","weekly"]},{"type":"null"}],"title":"Repeats"}},"type":"object","title":"TimeBlockPatch","description":"HIS [Edit Block], drawn on screens 4, 5 and 6. Only what is sent changes."},"TimeBlockReasonOut":{"properties":{"code":{"type":"string","title":"Code"},"label":{"type":"string","title":"Label"},"badge":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Badge"},"description":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Description"}},"type":"object","required":["code","label"],"title":"TimeBlockReasonOut","description":"ONE OF HIS SIX, as the platform holds it — his §9's enum with the word a person reads.\n\nAnswered rather than hardcoded so his list lives in ONE place: a screen that spelled its\nown six would drift the day he adds a seventh, and a code on a screen is not a reason\nanybody can read."},"TimeOffIn":{"properties":{"kind":{"type":"string","enum":["vacation","time_off"],"title":"Kind","default":"time_off"},"status":{"type":"string","enum":["pending","approved"],"title":"Status"},"starts_on":{"type":"string","format":"date","title":"Starts On"},"ends_on":{"type":"string","format":"date","title":"Ends On"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"}},"type":"object","required":["status","starts_on","ends_on"],"title":"TimeOffIn","description":"Whole days, both inclusive (040). The writer states the status - the two\nscreens disagree and the column refuses a default: a shop's schedule.edit\nholder may write `approved`; the professional's own request is `pending`."},"TimeOffOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"professional_id":{"type":"string","format":"uuid","title":"Professional Id"},"kind":{"type":"string","title":"Kind"},"status":{"type":"string","title":"Status"},"starts_on":{"type":"string","format":"date","title":"Starts On"},"ends_on":{"type":"string","format":"date","title":"Ends On"},"created_by":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Created By"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"}},"type":"object","required":["id","professional_id","kind","status","starts_on","ends_on","created_by","created_at"],"title":"TimeOffOut"},"TodayActivityOut":{"properties":{"services":{"type":"integer","title":"Services"},"memberships":{"type":"integer","title":"Memberships"},"products":{"type":"integer","title":"Products"},"clients":{"type":"integer","title":"Clients"}},"type":"object","required":["services","memberships","products","clients"],"title":"TodayActivityOut"},"TodayContextOut":{"properties":{"greeting_name":{"type":"string","title":"Greeting Name"},"timezone":{"type":"string","title":"Timezone"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"business_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Name"},"unread_notifications":{"type":"integer","title":"Unread Notifications"},"unread_messages":{"type":"integer","title":"Unread Messages"}},"type":"object","required":["greeting_name","timezone","unread_notifications","unread_messages"],"title":"TodayContextOut"},"TodayEarningsOut":{"properties":{"period":{"type":"string","title":"Period"},"date_from":{"type":"string","format":"date","title":"Date From"},"date_to":{"type":"string","format":"date","title":"Date To"},"total_cents":{"type":"integer","title":"Total Cents"},"services_cents":{"type":"integer","title":"Services Cents"},"memberships_cents":{"type":"integer","title":"Memberships Cents"},"shop_cents":{"type":"integer","title":"Shop Cents"},"reward_cents":{"type":"integer","title":"Reward Cents"},"reward_count":{"type":"integer","title":"Reward Count"}},"type":"object","required":["period","date_from","date_to","total_cents","services_cents","memberships_cents","shop_cents","reward_cents","reward_count"],"title":"TodayEarningsOut","description":"HIS §15's four sources, kept apart, and his §16's total from the ledger itself."},"TodayMessageOut":{"properties":{"conversation_id":{"type":"string","format":"uuid","title":"Conversation Id"},"title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Title"},"unread":{"type":"integer","title":"Unread"},"last_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Last At"}},"type":"object","required":["conversation_id","unread"],"title":"TodayMessageOut"},"TodayNoteOut":{"properties":{"appointment_id":{"type":"string","format":"uuid","title":"Appointment Id"},"client_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Client Name"},"note":{"type":"string","title":"Note"},"starts_at":{"type":"string","format":"date-time","title":"Starts At"},"service_name":{"type":"string","title":"Service Name"}},"type":"object","required":["appointment_id","note","starts_at","service_name"],"title":"TodayNoteOut"},"TodayOut":{"properties":{"context":{"$ref":"#/components/schemas/TodayContextOut"},"next_service":{"$ref":"#/components/schemas/NextServiceOut"},"earnings":{"additionalProperties":{"$ref":"#/components/schemas/TodayEarningsOut"},"type":"object","title":"Earnings"},"activity":{"$ref":"#/components/schemas/TodayActivityOut"},"attention":{"$ref":"#/components/schemas/NeedsAttentionOut"},"reviews":{"items":{"$ref":"#/components/schemas/TodayReviewOut"},"type":"array","title":"Reviews"},"notes":{"items":{"$ref":"#/components/schemas/TodayNoteOut"},"type":"array","title":"Notes"},"messages":{"items":{"$ref":"#/components/schemas/TodayMessageOut"},"type":"array","title":"Messages"},"schedule":{"$ref":"#/components/schemas/ProfessionalDayOut"},"instant_payout":{"$ref":"#/components/schemas/InstantPayoutOut"},"unavailable":{"items":{"type":"string"},"type":"array","title":"Unavailable","default":[]}},"type":"object","required":["context","next_service","earnings","activity","attention","reviews","notes","messages","schedule","instant_payout"],"title":"TodayOut"},"TodayReviewOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"rating":{"type":"integer","title":"Rating"},"comment":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Comment"},"author_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Author Name"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"answered":{"type":"boolean","title":"Answered"}},"type":"object","required":["id","rating","created_at","answered"],"title":"TodayReviewOut"},"TokenPair":{"properties":{"access_token":{"type":"string","title":"Access Token"},"refresh_token":{"type":"string","title":"Refresh Token"},"token_type":{"type":"string","title":"Token Type","default":"Bearer"},"expires_in":{"type":"integer","title":"Expires In"}},"type":"object","required":["access_token","refresh_token","expires_in"],"title":"TokenPair"},"TopRatedOut":{"properties":{"ranking_version":{"type":"string","title":"Ranking Version"},"basis":{"type":"string","enum":["bayesian_weighted_rating","insufficient_data"],"title":"Basis"},"formula":{"type":"string","title":"Formula"},"inputs":{"items":{"type":"string"},"type":"array","title":"Inputs"},"tie_break":{"items":{"type":"string"},"type":"array","title":"Tie Break"},"min_reviews":{"type":"integer","title":"Min Reviews"},"fallback":{"type":"string","title":"Fallback"},"candidates":{"type":"integer","title":"Candidates"},"area_mean_rating":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Area Mean Rating"},"area_mean_count":{"anyOf":[{"type":"number"},{"type":"null"}],"title":"Area Mean Count"},"items":{"items":{"$ref":"#/components/schemas/RankedBusinessOut"},"type":"array","title":"Items","default":[]}},"type":"object","required":["ranking_version","basis","formula","inputs","tie_break","min_reviews","fallback","candidates"],"title":"TopRatedOut","description":"Discover's Top Rated / \"Highly Rated Near You\" — HIS DIRECTIVE 3 §6 + §20.\n\nThe rule used to live in the app. It now lives in the server and this response\nDOCUMENTS it on every call, so that iOS, Android, Web and the admin's\nanalytics cannot disagree about who is top rated:\n\n    ranking_version   'top_rated.v1' — bump it when the formula changes\n    basis             'bayesian_weighted_rating', or 'insufficient_data' when\n                      no rated business is in range (items is then EMPTY)\n    formula / inputs / tie_break / min_reviews / fallback\n                      the contract, in words, as he listed them\n    area_mean_rating  C and m in the formula, for this call's candidate set\n    area_mean_count\n    items             ranked cards, each with its score and explanation"},"TopSellingOut":{"properties":{"ranking_version":{"type":"string","title":"Ranking Version"},"window_days":{"type":"integer","title":"Window Days"},"window":{"type":"string","title":"Window","default":"rolling"},"window_approved":{"type":"boolean","title":"Window Approved"},"scopes":{"items":{"type":"string"},"type":"array","title":"Scopes","default":[]},"min_units":{"type":"integer","title":"Min Units"},"units_sold":{"type":"string","title":"Units Sold"},"excluded":{"items":{"type":"string"},"type":"array","title":"Excluded","default":[]},"tie_break":{"items":{"type":"string"},"type":"array","title":"Tie Break","default":[]},"scope":{"type":"string","title":"Scope"},"items":{"items":{"$ref":"#/components/schemas/ProductCardOut"},"type":"array","title":"Items","default":[]}},"type":"object","required":["ranking_version","window_days","window_approved","min_units","units_sold","scope"],"title":"TopSellingOut","description":"Discover's Shop rail — \"Top Selling Beauty Products\" — with its rule\npublished. HIS DIRECTIVE 4 par.14, closed by HIS DECISION 144.\n\nThe copy already matched the signal; what was missing was the definition:\ntop selling SINCE WHEN, counting what, minus what, ties broken how. All of it\nrides here, and `window_approved` is now TRUE — he chose the window himself\non 2026-09-08: thirty ROLLING days, net of returns."},"TriageIn":{"properties":{"priority":{"anyOf":[{"type":"string","enum":["critical","urgent","high","medium","low"]},{"type":"null"}],"title":"Priority"},"impact":{"anyOf":[{"type":"string","enum":["low","medium","high"]},{"type":"null"}],"title":"Impact"},"impact_amount_cents":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Impact Amount Cents"},"assigned_to":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Assigned To"},"tags":{"anyOf":[{"items":{"type":"string"},"type":"array"},{"type":"null"}],"title":"Tags"},"status":{"anyOf":[{"type":"string","const":"in_review"},{"type":"null"}],"title":"Status"}},"type":"object","title":"TriageIn","description":"What support sets on a case: priority (the SLA follows it, as drawn), impact,\nassignee, tags, or \"In Review\"."},"TwoFactorAdminDisableIn":{"properties":{"reason":{"type":"string","maxLength":500,"minLength":3,"title":"Reason"}},"type":"object","required":["reason"],"title":"TwoFactorAdminDisableIn","description":"Turning off somebody ELSE's second factor.\n\nThe reason is mandatory here and mandatory in the database — a CHECK\nconstraint refuses the audit row without it. This is the most dangerous\noperation the feature adds, and an administrator must not be able to perform\nit without saying why, in their own words."},"TwoFactorConfirmIn":{"properties":{"code":{"type":"string","maxLength":8,"minLength":6,"title":"Code","description":"The code currently shown by the authenticator app."}},"type":"object","required":["code"],"title":"TwoFactorConfirmIn"},"TwoFactorDisabledOut":{"properties":{"subject_user_id":{"type":"string","format":"uuid","title":"Subject User Id"},"sessions_ended":{"type":"integer","title":"Sessions Ended"}},"type":"object","required":["subject_user_id","sessions_ended"],"title":"TwoFactorDisabledOut"},"TwoFactorEnrolmentOut":{"properties":{"secret":{"type":"string","title":"Secret"},"otpauth_uri":{"type":"string","title":"Otpauth Uri"},"digits":{"type":"integer","title":"Digits"},"period_seconds":{"type":"integer","title":"Period Seconds"},"algorithm":{"type":"string","title":"Algorithm"}},"type":"object","required":["secret","otpauth_uri","digits","period_seconds","algorithm"],"title":"TwoFactorEnrolmentOut","description":"The one and only time the secret leaves the server.\n\nAfter confirmation there is no endpoint that returns it again — not to the\nperson, not to an administrator, not in any list. A secret the platform will\nre-display is a secret anybody holding a session can steal at leisure."},"TwoFactorEventOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"subject_user_id":{"type":"string","format":"uuid","title":"Subject User Id"},"actor_user_id":{"type":"string","format":"uuid","title":"Actor User Id"},"actor_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actor Role"},"action":{"type":"string","title":"Action"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"},"detail":{"additionalProperties":true,"type":"object","title":"Detail"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","subject_user_id","actor_user_id","actor_role","action","reason","detail","created_at"],"title":"TwoFactorEventOut"},"TwoFactorProofIn":{"properties":{"code":{"anyOf":[{"type":"string","maxLength":8,"minLength":6},{"type":"null"}],"title":"Code"},"recovery_code":{"anyOf":[{"type":"string","maxLength":32,"minLength":8},{"type":"null"}],"title":"Recovery Code"}},"type":"object","title":"TwoFactorProofIn","description":"One factor or the other. Both fields optional in the schema and exactly\none required in practice — expressed in the service rather than here so the\nrefusal carries the same envelope and the same code as every other."},"TwoFactorStatusOut":{"properties":{"enabled":{"type":"boolean","title":"Enabled"},"pending":{"type":"boolean","title":"Pending"},"confirmed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Confirmed At"},"recovery_codes_remaining":{"type":"integer","title":"Recovery Codes Remaining"},"session_verified":{"type":"boolean","title":"Session Verified"},"session_verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Session Verified At"},"required":{"type":"boolean","title":"Required"},"locked_seconds":{"type":"integer","title":"Locked Seconds","default":0}},"type":"object","required":["enabled","pending","recovery_codes_remaining","session_verified","required"],"title":"TwoFactorStatusOut","description":"What this person's second factor looks like. NEVER the secret.\n\n`enabled` and `pending` are two different facts and both are here on\npurpose: an enrolment that was started and never confirmed protects nothing,\nand an app that showed one as the other would tell an administrator they\nwere safe when they were not."},"TwoFactorVerifiedOut":{"properties":{"factor":{"type":"string","title":"Factor"},"verified_at":{"type":"string","format":"date-time","title":"Verified At"},"recovery_codes_remaining":{"type":"integer","title":"Recovery Codes Remaining"}},"type":"object","required":["factor","verified_at","recovery_codes_remaining"],"title":"TwoFactorVerifiedOut"},"UnconfiguredBranchOut":{"properties":{"branch_id":{"type":"string","format":"uuid","title":"Branch Id"},"branch_name":{"type":"string","title":"Branch Name"}},"type":"object","required":["branch_id","branch_name"],"title":"UnconfiguredBranchOut","description":"A location of this business that has never counted this product.\n\nHis words for it: \"Inventory Not Configured\"."},"UserOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"},"full_name":{"type":"string","title":"Full Name"},"status":{"type":"string","title":"Status"},"email_verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Email Verified At"},"phone_verified_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Phone Verified At"},"locale":{"type":"string","title":"Locale"},"avatar_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Avatar Key"},"username":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Username"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"personalized_recommendations":{"type":"boolean","title":"Personalized Recommendations","default":true},"two_factor_enabled":{"type":"boolean","title":"Two Factor Enabled","default":false},"date_of_birth":{"anyOf":[{"type":"string","format":"date"},{"type":"null"}],"title":"Date Of Birth"},"created_at":{"type":"string","format":"date-time","title":"Created At"},"platform_role":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Platform Role"}},"type":"object","required":["id","email","phone","full_name","status","locale","avatar_key","created_at"],"title":"UserOut"},"UsernameAvailabilityOut":{"properties":{"username":{"type":"string","title":"Username"},"available":{"type":"boolean","title":"Available"},"suggestions":{"items":{"type":"string"},"type":"array","title":"Suggestions","default":[]}},"type":"object","required":["username","available"],"title":"UsernameAvailabilityOut","description":"What his field shows while somebody types: a tick, or three chips."},"ValidationError":{"properties":{"loc":{"items":{"anyOf":[{"type":"string"},{"type":"integer"}]},"type":"array","title":"Location"},"msg":{"type":"string","title":"Message"},"type":{"type":"string","title":"Error Type"},"input":{"title":"Input"},"ctx":{"type":"object","title":"Context"}},"type":"object","required":["loc","msg","type"],"title":"ValidationError"},"VariantIn":{"properties":{"attribute":{"type":"string","enum":["size","colour","quantity","format","option"],"title":"Attribute","default":"size"},"label":{"type":"string","maxLength":80,"minLength":1,"title":"Label"},"price_cents":{"anyOf":[{"type":"integer","exclusiveMinimum":0.0},{"type":"null"}],"title":"Price Cents"},"sku":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Sku"},"barcode":{"anyOf":[{"type":"string","pattern":"^[0-9]{8,14}$"},{"type":"null"}],"title":"Barcode"},"opening_stock":{"items":{"$ref":"#/components/schemas/OpeningStockIn"},"type":"array","title":"Opening Stock"}},"type":"object","required":["label"],"title":"VariantIn","description":"One of the things a product is sold as — his decision 80.\n\n`attribute` is the AXIS and is fixed by the first variant: a list that is\nhalf sizes and half colours is two selectors printed on top of each other.\n`price_cents` NULL inherits the product's, the platform's own idiom for an\noverride."},"VariantOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"label":{"type":"string","title":"Label"},"price_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Price Cents"},"sku":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sku"},"barcode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Barcode"},"sort_order":{"type":"integer","title":"Sort Order","default":0},"is_active":{"type":"boolean","title":"Is Active","default":true}},"type":"object","required":["id","label"],"title":"VariantOut"},"VariantUpdateIn":{"properties":{"label":{"type":"string","maxLength":80,"minLength":1,"title":"Label"},"price_cents":{"anyOf":[{"type":"integer","exclusiveMinimum":0.0},{"type":"null"}],"title":"Price Cents"},"sku":{"anyOf":[{"type":"string","maxLength":64,"minLength":1},{"type":"null"}],"title":"Sku"},"barcode":{"anyOf":[{"type":"string","pattern":"^[0-9]{8,14}$"},{"type":"null"}],"title":"Barcode"},"is_active":{"type":"boolean","title":"Is Active","default":true}},"type":"object","required":["label"],"title":"VariantUpdateIn"},"VerificationCheckOut":{"properties":{"kind":{"type":"string","title":"Kind"},"label":{"type":"string","title":"Label"},"document_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Document Name"},"status":{"type":"string","title":"Status"},"document_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Document Key"},"document_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Document Url"},"document_file_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Document File Name"},"submitted_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Submitted At"},"decided_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Decided At"},"reason":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Reason"}},"type":"object","required":["kind","label","status"],"title":"VerificationCheckOut","description":"One of his five checks. `document_name` is his Documents list's name for\nthe check's document (three of the five); `document_file_name` is what the\nowner called the file they sent. `reason` reaches the owner only when it was\naddressed to them (changes requested, rejected)."},"VerificationCodeIn":{"properties":{"code":{"type":"string","maxLength":12,"minLength":4,"title":"Code"}},"type":"object","required":["code"],"title":"VerificationCodeIn","description":"His six boxes. Digits only, and exactly six — a screen that accepts\n\"48 29 13\" and a server that does not is a person told they typed it wrong\nwhen they did not, so the whitespace is stripped before it gets here."},"VerificationEventOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"subject_type":{"type":"string","title":"Subject Type"},"subject_id":{"type":"string","format":"uuid","title":"Subject Id"},"action":{"type":"string","title":"Action"},"actor_id":{"type":"string","format":"uuid","title":"Actor Id"},"actor_role":{"type":"string","title":"Actor Role"},"reason":{"type":"string","title":"Reason"},"before_state":{"additionalProperties":true,"type":"object","title":"Before State"},"after_state":{"additionalProperties":true,"type":"object","title":"After State"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","subject_type","subject_id","action","actor_id","actor_role","reason","before_state","after_state","created_at"],"title":"VerificationEventOut","description":"One decision, as it was recorded. Append-only: nothing here is editable."},"VerificationStatusOut":{"properties":{"verified":{"type":"boolean","title":"Verified"},"channel":{"type":"string","title":"Channel"},"sent_to":{"type":"string","title":"Sent To"},"code_pending":{"type":"boolean","title":"Code Pending"},"delivered":{"type":"boolean","title":"Delivered","default":true},"attempts_left":{"type":"integer","title":"Attempts Left"},"resend_in_seconds":{"type":"integer","title":"Resend In Seconds"},"digits":{"type":"integer","title":"Digits"}},"type":"object","required":["verified","channel","sent_to","code_pending","attempts_left","resend_in_seconds","digits"],"title":"VerificationStatusOut","description":"Everything his ONB-003 needs to draw itself, and nothing more.\n\nNOT THE CODE. Obvious, and worth saying: an endpoint that returned it would\nmake the whole mechanism theatre."},"VerifyEmailIn":{"properties":{"token":{"type":"string","maxLength":200,"minLength":16,"title":"Token"}},"type":"object","required":["token"],"title":"VerifyEmailIn"},"VisibilityIn":{"properties":{"visibility":{"type":"string","enum":["private","business_only","public"],"title":"Visibility"}},"type":"object","required":["visibility"],"title":"VisibilityIn"},"WalletOut":{"properties":{"balance_cents":{"type":"integer","title":"Balance Cents"}},"type":"object","required":["balance_cents"],"title":"WalletOut"},"WebhookEventOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"provider":{"type":"string","title":"Provider"},"provider_event_id":{"type":"string","title":"Provider Event Id"},"event_type":{"type":"string","title":"Event Type"},"signature_verified":{"type":"boolean","title":"Signature Verified"},"status":{"type":"string","title":"Status"},"attempts":{"type":"integer","title":"Attempts"},"last_error":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Last Error"},"received_at":{"type":"string","format":"date-time","title":"Received At"},"processed_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Processed At"}},"type":"object","required":["id","provider","provider_event_id","event_type","signature_verified","status","attempts","last_error","received_at","processed_at"],"title":"WebhookEventOut","description":"One inbound processor event, as recorded.\n\nThe reconciliation surface: what arrived, whether its signature checked out,\nwhether it was acted on, and — when it failed — why. `payload` is\ndeliberately absent: it can contain the processor's own customer details,\nand this list is read on a screen."},"WorkPlaceOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"timezone":{"type":"string","title":"Timezone"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"}},"type":"object","required":["id","name","timezone"],"title":"WorkPlaceOut","description":"One location this person works at, with the clock it keeps.\n\nHis Block Time (screen 8) and his Add Appointment (§14) both post a branch id, and a\nmembership that covers the whole business carries none - so the day says it."},"WorkSetupIn":{"properties":{"work_type":{"type":"string","enum":["business","chair","suite","independent_studio","mobile","client_home"],"title":"Work Type"},"ownership_model":{"anyOf":[{"type":"string","enum":["own_operation","at_a_business","renter"]},{"type":"null"}],"title":"Ownership Model"},"service_delivery_mode":{"anyOf":[{"type":"string","enum":["at_my_place","at_the_client","both"]},{"type":"null"}],"title":"Service Delivery Mode"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"chair_number":{"anyOf":[{"type":"string","maxLength":24},{"type":"null"}],"title":"Chair Number"},"booth_number":{"anyOf":[{"type":"string","maxLength":24},{"type":"null"}],"title":"Booth Number"},"floor":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Floor"},"place_name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Place Name"},"suite_number":{"anyOf":[{"type":"string","maxLength":24},{"type":"null"}],"title":"Suite Number"},"street":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Street"},"city":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"State"},"postal_code":{"anyOf":[{"type":"string","maxLength":24},{"type":"null"}],"title":"Postal Code"},"country":{"anyOf":[{"type":"string","maxLength":2},{"type":"null"}],"title":"Country"},"public_directions":{"anyOf":[{"type":"string","maxLength":280},{"type":"null"}],"title":"Public Directions"},"entrance_notes":{"anyOf":[{"type":"string","maxLength":280},{"type":"null"}],"title":"Entrance Notes"},"service_radius_miles":{"anyOf":[{"type":"integer","maximum":300.0,"minimum":1.0},{"type":"null"}],"title":"Service Radius Miles"},"service_areas":{"items":{"type":"string"},"type":"array","maxItems":40,"title":"Service Areas"},"travel_fee_cents":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Travel Fee Cents"},"minimum_booking_cents":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Minimum Booking Cents"},"public_address_visibility":{"type":"boolean","title":"Public Address Visibility","default":false},"status":{"type":"string","enum":["draft","published","hidden","archived"],"title":"Status","default":"draft"},"display_order":{"type":"integer","title":"Display Order","default":0}},"type":"object","required":["work_type"],"title":"WorkSetupIn","description":"HOW SOMEBODY WORKS — MY PROFILE v1.1 section 2. Which of these fields mean anything depends\non `work_type`, and `presence.check_work_setup` refuses the combinations his directive refuses,\nnaming the field; the database refuses them again (102_professional_work_setup.sql)."},"WorkSetupOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"work_type":{"type":"string","enum":["business","chair","suite","independent_studio","mobile","client_home"],"title":"Work Type"},"ownership_model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Ownership Model"},"service_delivery_mode":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Service Delivery Mode"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"business_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Business Name"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"branch_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Branch Name"},"chair_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Chair Number"},"booth_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Booth Number"},"floor":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Floor"},"place_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Place Name"},"suite_number":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Suite Number"},"street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Street"},"public_street":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Public Street"},"city":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"State"},"postal_code":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Postal Code"},"country":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Country"},"public_directions":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Public Directions"},"entrance_notes":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Entrance Notes"},"service_radius_miles":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Service Radius Miles"},"service_areas":{"items":{"type":"string"},"type":"array","title":"Service Areas"},"travel_fee_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Travel Fee Cents"},"minimum_booking_cents":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Minimum Booking Cents"},"public_address_visibility":{"type":"boolean","title":"Public Address Visibility"},"status":{"type":"string","enum":["draft","published","hidden","archived"],"title":"Status"},"display_order":{"type":"integer","title":"Display Order"}},"type":"object","required":["id","work_type","public_address_visibility","status","display_order"],"title":"WorkSetupOut","description":"The professional's own view: everything they typed, plus what of it is publishable.\n\n`public_street` is the street a client would see — his address switch answered once, here,\nso no screen has to decide it twice."},"WorkSetupPatch":{"properties":{"work_type":{"anyOf":[{"type":"string","enum":["business","chair","suite","independent_studio","mobile","client_home"]},{"type":"null"}],"title":"Work Type"},"ownership_model":{"anyOf":[{"type":"string","enum":["own_operation","at_a_business","renter"]},{"type":"null"}],"title":"Ownership Model"},"service_delivery_mode":{"anyOf":[{"type":"string","enum":["at_my_place","at_the_client","both"]},{"type":"null"}],"title":"Service Delivery Mode"},"business_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Business Id"},"branch_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Branch Id"},"chair_number":{"anyOf":[{"type":"string","maxLength":24},{"type":"null"}],"title":"Chair Number"},"booth_number":{"anyOf":[{"type":"string","maxLength":24},{"type":"null"}],"title":"Booth Number"},"floor":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Floor"},"place_name":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"Place Name"},"suite_number":{"anyOf":[{"type":"string","maxLength":24},{"type":"null"}],"title":"Suite Number"},"street":{"anyOf":[{"type":"string","maxLength":200},{"type":"null"}],"title":"Street"},"city":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"City"},"state":{"anyOf":[{"type":"string","maxLength":120},{"type":"null"}],"title":"State"},"postal_code":{"anyOf":[{"type":"string","maxLength":24},{"type":"null"}],"title":"Postal Code"},"country":{"anyOf":[{"type":"string","maxLength":2},{"type":"null"}],"title":"Country"},"public_directions":{"anyOf":[{"type":"string","maxLength":280},{"type":"null"}],"title":"Public Directions"},"entrance_notes":{"anyOf":[{"type":"string","maxLength":280},{"type":"null"}],"title":"Entrance Notes"},"service_radius_miles":{"anyOf":[{"type":"integer","maximum":300.0,"minimum":1.0},{"type":"null"}],"title":"Service Radius Miles"},"service_areas":{"anyOf":[{"items":{"type":"string"},"type":"array","maxItems":40},{"type":"null"}],"title":"Service Areas"},"travel_fee_cents":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Travel Fee Cents"},"minimum_booking_cents":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Minimum Booking Cents"},"public_address_visibility":{"anyOf":[{"type":"boolean"},{"type":"null"}],"title":"Public Address Visibility"},"status":{"anyOf":[{"type":"string","enum":["draft","published","hidden","archived"]},{"type":"null"}],"title":"Status"},"display_order":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Display Order"}},"type":"object","title":"WorkSetupPatch","description":"Only what is sent changes — including his four publication states."},"malu__domains__booking__schemas__CheckoutIn":{"properties":{"tip_cents":{"type":"integer","maximum":100000.0,"minimum":0.0,"title":"Tip Cents","default":0},"use_credit":{"type":"boolean","title":"Use Credit","default":false},"card_brand":{"anyOf":[{"type":"string","maxLength":32},{"type":"null"}],"title":"Card Brand"},"card_last4":{"anyOf":[{"type":"string","maxLength":4,"minLength":4},{"type":"null"}],"title":"Card Last4"},"card_number":{"anyOf":[{"type":"string","maxLength":24},{"type":"null"}],"title":"Card Number","description":"Test card number, mock provider only"}},"type":"object","title":"CheckoutIn","description":"Paying for an appointment.\n\nNo idempotency key is accepted from the caller: it is derived from the\nappointment itself, so one appointment can only ever produce one charge,\nhowever many times the button is pressed.\n\ncard_number is only ever a TEST number, and only against the mock provider —\nit chooses which outcome to simulate (4242… approves, 4000…0002 declines) so\nthe app's failure paths can be built before the client's Stripe account\nexists. With a real key it is ignored: real card details never touch this\nserver. They go from the phone straight to Stripe, and only a token comes back."},"malu__domains__commerce__schemas__CheckoutIn":{"properties":{"fulfillment":{"type":"string","enum":["pickup","delivery"],"title":"Fulfillment","default":"pickup"},"client_note":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Client Note"},"card_brand":{"anyOf":[{"type":"string","maxLength":20},{"type":"null"}],"title":"Card Brand"},"card_last4":{"anyOf":[{"type":"string","maxLength":4},{"type":"null"}],"title":"Card Last4"},"card_number":{"anyOf":[{"type":"string","maxLength":25},{"type":"null"}],"title":"Card Number"}},"type":"object","title":"CheckoutIn","description":"What the buyer decides. Not one field of it is an amount.\n\n`fulfillment` only accepts 'pickup'. Delivery is refused with a plain reason\nuntil the client sets shipping rules — the schema carries the value so\nturning it on is a decision rather than a migration."},"malu__domains__directory__schemas__EvidenceIn":{"properties":{"storage_key":{"type":"string","maxLength":500,"minLength":1,"title":"Storage Key"},"mime_type":{"type":"string","maxLength":120,"minLength":3,"title":"Mime Type"},"doc_type":{"anyOf":[{"type":"string","maxLength":40},{"type":"null"}],"title":"Doc Type"},"byte_size":{"anyOf":[{"type":"integer","minimum":0.0},{"type":"null"}],"title":"Byte Size"}},"type":"object","required":["storage_key","mime_type"],"title":"EvidenceIn","description":"A document already uploaded to object storage. Only its KEY travels here —\nthis domain never receives or stores file bytes."},"malu__domains__directory__schemas__EvidenceOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"storage_key":{"type":"string","title":"Storage Key"},"mime_type":{"type":"string","title":"Mime Type"},"doc_type":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Doc Type"},"byte_size":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Byte Size"},"uploaded_at":{"type":"string","format":"date-time","title":"Uploaded At"}},"type":"object","required":["id","storage_key","mime_type","doc_type","byte_size","uploaded_at"],"title":"EvidenceOut"},"malu__domains__engagement__schemas__MessageIn":{"properties":{"body":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"title":"Body"},"attachment_key":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Attachment Key"}},"type":"object","title":"MessageIn","description":"One of the two is required — the database enforces it, and so do we, so the\nclient gets an answer it can act on instead of a constraint violation."},"malu__domains__engagement__schemas__MessageOut":{"properties":{"id":{"type":"integer","title":"Id"},"conversation_id":{"type":"string","format":"uuid","title":"Conversation Id"},"sender_user_id":{"type":"string","format":"uuid","title":"Sender User Id"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"},"attachment_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attachment Key"},"read_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Read At"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","conversation_id","sender_user_id","body","attachment_key","read_at","created_at"],"title":"MessageOut"},"malu__domains__knowledge__schemas__EventOut":{"properties":{"id":{"type":"integer","title":"Id"},"article_id":{"type":"string","format":"uuid","title":"Article Id"},"article_title":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Article Title"},"article_domain":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Article Domain"},"kind":{"type":"string","title":"Kind"},"actor_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Actor Id"},"actor_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Actor Name"},"title":{"type":"string","title":"Title"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"},"version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Version"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","article_id","kind","actor_id","actor_name","title","detail","version","created_at"],"title":"EventOut"},"malu__domains__knowledge__schemas__PersonOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"}},"type":"object","required":["id","name"],"title":"PersonOut"},"malu__domains__knowledge__schemas__SummaryOut":{"properties":{"published":{"type":"integer","title":"Published"},"pending_review":{"type":"integer","title":"Pending Review"},"outdated":{"type":"integer","title":"Outdated"},"drafts":{"type":"integer","title":"Drafts"},"archived":{"type":"integer","title":"Archived"},"domains":{"items":{"$ref":"#/components/schemas/DomainHealthOut"},"type":"array","title":"Domains"},"recently_updated":{"type":"integer","title":"Recently Updated"},"recent_days":{"type":"integer","title":"Recent Days"},"frequently_used":{"type":"integer","title":"Frequently Used"},"needs_review":{"type":"integer","title":"Needs Review"}},"type":"object","required":["published","pending_review","outdated","drafts","archived","domains","recently_updated","recent_days","frequently_used","needs_review"],"title":"SummaryOut","description":"His KNOWLEDGE HEALTH and KNOWLEDGE DOMAINS, counted from the rows."},"malu__domains__organization__language_admin__LanguageOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"code":{"type":"string","title":"Code"},"name":{"type":"string","title":"Name"},"aliases":{"items":{"type":"string"},"type":"array","title":"Aliases","default":[]},"is_active":{"type":"boolean","title":"Is Active","default":true}},"type":"object","required":["id","code","name"],"title":"LanguageOut"},"malu__domains__professionals__schemas__LanguageOut":{"properties":{"code":{"type":"string","title":"Code"},"name":{"type":"string","title":"Name"}},"type":"object","required":["code","name"],"title":"LanguageOut"},"malu__domains__support__schemas__EventOut":{"properties":{"id":{"type":"integer","title":"Id"},"kind":{"type":"string","title":"Kind"},"actor_id":{"anyOf":[{"type":"string","format":"uuid"},{"type":"null"}],"title":"Actor Id"},"actor_role":{"type":"string","title":"Actor Role"},"title":{"type":"string","title":"Title"},"detail":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Detail"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","kind","actor_id","actor_role","title","detail","created_at"],"title":"EventOut"},"malu__domains__support__schemas__EvidenceIn":{"properties":{"storage_key":{"type":"string","maxLength":512,"title":"Storage Key"},"kind":{"type":"string","enum":["photo","video","document","receipt"],"title":"Kind"},"label":{"type":"string","maxLength":80,"minLength":1,"title":"Label"}},"type":"object","required":["storage_key","kind","label"],"title":"EvidenceIn"},"malu__domains__support__schemas__EvidenceOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"kind":{"type":"string","title":"Kind"},"storage_key":{"type":"string","title":"Storage Key"},"label":{"type":"string","title":"Label"},"uploaded_by":{"type":"string","format":"uuid","title":"Uploaded By"},"uploaded_role":{"type":"string","title":"Uploaded Role"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","kind","storage_key","label","uploaded_by","uploaded_role","created_at"],"title":"EvidenceOut"},"malu__domains__support__schemas__MessageIn":{"properties":{"body":{"anyOf":[{"type":"string","maxLength":4000},{"type":"null"}],"title":"Body"},"attachment_key":{"anyOf":[{"type":"string","maxLength":512},{"type":"null"}],"title":"Attachment Key"},"internal":{"type":"boolean","title":"Internal","default":false}},"type":"object","title":"MessageIn"},"malu__domains__support__schemas__MessageOut":{"properties":{"id":{"type":"integer","title":"Id"},"sender_id":{"type":"string","format":"uuid","title":"Sender Id"},"sender_role":{"type":"string","title":"Sender Role"},"sender_name":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Sender Name"},"body":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Body"},"attachment_key":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Attachment Key"},"is_internal":{"type":"boolean","title":"Is Internal"},"created_at":{"type":"string","format":"date-time","title":"Created At"}},"type":"object","required":["id","sender_id","sender_role","sender_name","body","attachment_key","is_internal","created_at"],"title":"MessageOut"},"malu__domains__support__schemas__PersonOut":{"properties":{"id":{"type":"string","format":"uuid","title":"Id"},"name":{"type":"string","title":"Name"},"email":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Email"},"phone":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Phone"}},"type":"object","required":["id","name"],"title":"PersonOut"},"malu__domains__support__schemas__SummaryOut":{"properties":{"active_total":{"type":"integer","title":"Active Total"},"by_priority":{"additionalProperties":{"type":"integer"},"type":"object","title":"By Priority"},"by_status":{"additionalProperties":{"type":"integer"},"type":"object","title":"By Status"},"by_category":{"additionalProperties":{"type":"integer"},"type":"object","title":"By Category"},"new_today":{"type":"integer","title":"New Today"},"resolved_today":{"type":"integer","title":"Resolved Today"},"sla_at_risk":{"type":"integer","title":"Sla At Risk"},"sla_overdue":{"type":"integer","title":"Sla Overdue"},"unassigned":{"type":"integer","title":"Unassigned"}},"type":"object","required":["active_total","by_priority","by_status","by_category","new_today","resolved_today","sla_at_risk","sla_overdue","unassigned"],"title":"SummaryOut","description":"His 5-second status: the counters of the Command Center."},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message","request_id"],"properties":{"code":{"type":"string","description":"Stable machine-readable reason. Branch on this, never on the message.","example":"email_taken"},"message":{"type":"string","description":"Written for the person to read, in their language. Safe to show as-is.","example":"That email is already registered."},"detail":{"type":"string","description":"For the developer. Absent in production for unexpected failures.","example":"users.email unique violation"},"request_id":{"type":"string","description":"This request's id, also in the X-Request-Id response header. Quote it in a support ticket.","example":"9f2c1c7a4b0e4d1f9c3a5e8b7d6f2a10"}}}}}},"securitySchemes":{"BearerAuth":{"type":"http","description":"The access token from POST /v1/auth/login, sent as `Authorization: Bearer <token>`.","scheme":"bearer","bearerFormat":"JWT"}}}}