{"openapi":"3.1.0","info":{"title":"RebookAI API","version":"0.1.0","description":"AI-native appointment recovery platform. The web UI consumes this same API."},"servers":[{"url":"/"}],"components":{"schemas":{"HealthResponse":{"type":"object","properties":{"status":{"type":"string","enum":["ok"]},"version":{"type":"string"},"time":{"type":"string","format":"date-time"}},"required":["status","version","time"]},"LoginResponse":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","format":"email"},"name":{"type":"string"},"role":{"type":"string","enum":["SUPER_ADMIN","BUSINESS_ADMIN","STAFF"]}},"required":["id","email","name","role"]}},"required":["user"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"},"details":{}},"required":["code","message"]}},"required":["error"]},"LoginRequest":{"type":"object","properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","minLength":1}},"required":["email","password"]},"MeResponse":{"type":"object","properties":{"userId":{"type":"string","format":"uuid"},"tenantId":{"type":["string","null"],"format":"uuid"},"role":{"type":"string","enum":["SUPER_ADMIN","BUSINESS_ADMIN","STAFF"]}},"required":["userId","tenantId","role"]},"SettingsResponse":{"type":"object","properties":{"settings":{"type":"array","items":{"$ref":"#/components/schemas/EffectiveSetting"}}},"required":["settings"]},"EffectiveSetting":{"type":"object","properties":{"key":{"type":"string"},"value":{},"source":{"type":"string","enum":["platform_default","industry_template","tenant_override"]},"scope":{"type":"string","enum":["SUPER_ADMIN_ONLY","TENANT_EDITABLE"]},"category":{"type":"string"},"description":{"type":"string"}},"required":["key","source","scope","category","description"]},"UpdateSettingRequest":{"type":"object","properties":{"value":{}}}},"parameters":{}},"paths":{"/v1/health":{"get":{"tags":["system"],"summary":"Liveness check","responses":{"200":{"description":"Service is up","content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthResponse"}}}}}}},"/v1/auth/login":{"post":{"tags":["auth"],"summary":"Log in with email + password; sets the session cookie","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginRequest"}}}},"responses":{"200":{"description":"Authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"401":{"description":"Invalid credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/auth/logout":{"post":{"tags":["auth"],"summary":"Clear the session cookie","responses":{"200":{"description":"Logged out"}}}},"/v1/auth/me":{"get":{"tags":["auth"],"summary":"Current session","responses":{"200":{"description":"Session details","content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/settings":{"get":{"tags":["settings"],"summary":"Effective settings for the session tenant (three-layer resolution)","responses":{"200":{"description":"Resolved settings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SettingsResponse"}}}},"401":{"description":"Not authenticated","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/settings/{key}":{"patch":{"tags":["settings"],"summary":"Set a tenant override for one setting key","parameters":[{"schema":{"type":"string"},"required":true,"name":"key","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSettingRequest"}}}},"responses":{"200":{"description":"Updated"},"400":{"description":"Wrong value type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key not tenant-editable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/contacts":{"post":{"tags":["contacts"],"summary":"Create a contact with per-channel consent records","responses":{"201":{"description":"Created"}}},"get":{"tags":["contacts"],"summary":"List contacts","responses":{"200":{"description":"Contacts"}}}},"/v1/waitlist":{"post":{"tags":["waitlist"],"summary":"Add a waitlist entry","responses":{"201":{"description":"Created"}}},"get":{"tags":["waitlist"],"summary":"List active waitlist entries","responses":{"200":{"description":"Entries"}}}},"/v1/waitlist/import":{"post":{"tags":["waitlist"],"summary":"Bulk import waitlist from CSV (name,phone,email,service,priority,consent_sms)","responses":{"200":{"description":"Import result"}}}},"/v1/booking-events":{"post":{"tags":["recovery"],"summary":"Report a cancellation/absence; creates a recovery job and starts outreach","responses":{"201":{"description":"Created"}}},"get":{"tags":["recovery"],"summary":"List booking events","responses":{"200":{"description":"Events"}}}},"/v1/recoveries":{"get":{"tags":["recovery"],"summary":"List recovery jobs with attempt status (live board data)","responses":{"200":{"description":"Recoveries"}}}},"/v1/recoveries/{id}":{"get":{"tags":["recovery"],"summary":"Recovery job detail with attempts, scores and holds","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Recovery"}}}},"/v1/recoveries/{id}/cancel":{"post":{"tags":["recovery"],"summary":"Manually release a recovery job","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"New state"}}}},"/v1/tenant/profile":{"get":{"tags":["settings"],"summary":"Tenant name + locale/currency/timezone for formatting","responses":{"200":{"description":"Profile"}}}},"/v1/locations":{"get":{"tags":["settings"],"summary":"List locations","responses":{"200":{"description":"Locations"}}}},"/v1/providers":{"get":{"tags":["settings"],"summary":"List providers","responses":{"200":{"description":"Providers"}}}},"/v1/api-keys":{"get":{"tags":["integrations"],"summary":"List API keys (hashes only)","responses":{"200":{"description":"Keys"}}},"post":{"tags":["integrations"],"summary":"Create an API key (full key returned once)","responses":{"201":{"description":"Created"}}}},"/v1/api-keys/{id}":{"delete":{"tags":["integrations"],"summary":"Revoke an API key","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Revoked"}}}},"/v1/absences":{"post":{"tags":["recovery"],"summary":"Report a provider absence: blast affected patients, auto or manual reschedule per platform setting","responses":{"201":{"description":"Blast result"}}},"get":{"tags":["recovery"],"summary":"Absence events with notify/queue/rebooked progress","responses":{"200":{"description":"Absences"}}}},"/v1/inbound/sms":{"post":{"tags":["recovery"],"summary":"Inbound SMS (sandbox); YES/NO/STOP routed through the state machine","responses":{"200":{"description":"Interpretation + reply"}}}}},"webhooks":{}}