{"openapi":"3.1.0","info":{"title":"Freelance OS API","version":"1.0.0","description":"API publique Freelance OS. Versioning par URL (/v1). Auth Bearer JWT (Supabase). Scope multi-tenant via header X-Workspace-Id."},"servers":[{"url":"https://api.freelance-os.fr/v1","description":"Production"},{"url":"http://localhost:4010/v1","description":"Local dev"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Access token Supabase. Format : Authorization: Bearer <jwt>"},"apiKeyAuth":{"type":"apiKey","in":"header","name":"X-API-Key","description":"API key long-lived (format fos_sk_live_...). Genere depuis /settings/api-keys dans Kernel. Une cle est scopee a un seul workspace."}},"schemas":{},"parameters":{}},"paths":{"/me":{"get":{"tags":["Identity"],"summary":"Get current user","description":"Retourne le profil de l'user authentifié + la liste de ses workspaces actifs + l'active_workspace_id depuis le claim JWT si présent.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"email":{"type":"string","nullable":true,"format":"email"}},"required":["id","email"]},"workspaces":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"name":{"type":"string","minLength":1},"role":{"type":"string"}},"required":["id","slug","name","role"]}},"active_workspace_id":{"type":"string","nullable":true,"format":"uuid"}},"required":["user","workspaces","active_workspace_id"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/workspaces":{"get":{"tags":["Identity"],"summary":"List my workspaces","description":"Liste les workspaces actifs auxquels l'user appartient.","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"name":{"type":"string","minLength":1},"role":{"type":"string"}},"required":["id","slug","name","role"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/workspaces/{id}":{"get":{"tags":["Identity"],"summary":"Get workspace by id","description":"Retourne le workspace si l'user en est membre actif. 403 sinon (pas 404, pour ne pas leak l'existence).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"name":{"type":"string","minLength":1},"role":{"type":"string"}},"required":["id","slug","name","role"]}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/workspaces/{id}/members":{"get":{"tags":["Identity"],"summary":"List workspace members","description":"Liste les membres (actifs + invités + suspendus) du workspace avec leur profil. 403 si non-membre.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"user_id":{"type":"string","format":"uuid"},"role":{"type":"string"},"status":{"type":"string","enum":["active","invited","suspended"]},"created_at":{"type":"string","format":"date-time"},"accepted_at":{"type":"string","nullable":true,"format":"date-time"},"profile":{"type":"object","nullable":true,"properties":{"email":{"type":"string","nullable":true,"format":"email"},"full_name":{"type":"string","nullable":true},"avatar_url":{"type":"string","nullable":true,"format":"uri"}},"required":["email","full_name","avatar_url"]}},"required":["user_id","role","status","created_at","accepted_at","profile"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/booking/{workspaceId}/bookings":{"get":{"tags":["Booking"],"summary":"List bookings of a workspace","description":"Retourne la liste des bookings (confirmed, completed, cancelled, ...) du workspace. 403 si user non-membre. Filtrage status + since + limit en query.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","format":"date-time"},"required":false,"name":"since","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"contact_id":{"type":"string","nullable":true,"format":"uuid"},"event_type_id":{"type":"string","nullable":true,"format":"uuid"},"scheduled_at":{"type":"string","format":"date-time"},"status":{"type":"string"}},"required":["id","contact_id","event_type_id","scheduled_at","status"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/booking/{workspaceId}/event-types":{"get":{"tags":["Booking"],"summary":"List event types","description":"Retourne les event types configurés sur le workspace (slug, durée, etc.).","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workspaceId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string"},"name":{"type":"string"},"duration_minutes":{"type":"integer","minimum":0,"exclusiveMinimum":true},"is_active":{"type":"boolean"}},"required":["id","slug","name","duration_minutes","is_active"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/crm/{workspaceId}/contacts":{"get":{"tags":["CRM"],"summary":"List contacts","description":"Liste les contacts d'un workspace. Filtres optionnels : lifecycle_stage, source, q (recherche texte), limit.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"lifecycle_stage","in":"query"},{"schema":{"type":"string"},"required":false,"name":"source","in":"query"},{"schema":{"type":"string"},"required":false,"name":"q","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"email":{"type":"string","nullable":true,"format":"email"},"first_name":{"type":"string","nullable":true},"last_name":{"type":"string","nullable":true},"linkedin_url":{"type":"string","nullable":true,"format":"uri"},"lifecycle_stage":{"type":"string"},"source":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["id","workspace_id","email","first_name","last_name","linkedin_url","lifecycle_stage","source","created_at"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/crm/{workspaceId}/contacts/{contactId}":{"get":{"tags":["CRM"],"summary":"Get contact by id","description":"Détail d'un contact spécifique.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"contactId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"email":{"type":"string","nullable":true,"format":"email"},"first_name":{"type":"string","nullable":true},"last_name":{"type":"string","nullable":true},"linkedin_url":{"type":"string","nullable":true,"format":"uri"},"lifecycle_stage":{"type":"string"},"source":{"type":"string"},"created_at":{"type":"string","format":"date-time"}},"required":["id","workspace_id","email","first_name","last_name","linkedin_url","lifecycle_stage","source","created_at"]}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"404":{"description":"Not Found","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/workbench/{workspaceId}/projects":{"get":{"tags":["Workbench"],"summary":"List projects","description":"Liste les projets du workspace. Filtre status + limit.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"description":{"type":"string","nullable":true},"owner_id":{"type":"string","nullable":true,"format":"uuid"},"status":{"type":"string"},"deadline":{"type":"string","nullable":true,"format":"date-time"},"color":{"type":"string","nullable":true},"icon":{"type":"string","nullable":true},"created_at":{"type":"string","format":"date-time"},"contact_id":{"type":"string","nullable":true,"format":"uuid"}},"required":["id","name","description","owner_id","status","deadline","color","icon","created_at","contact_id"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/workbench/{workspaceId}/tasks":{"get":{"tags":["Workbench"],"summary":"List tasks","description":"Liste les tâches du workspace. Filtres status, projectId, limit.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"project_id","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"status":{"type":"string"},"priority":{"type":"string"},"project_id":{"type":"string","nullable":true,"format":"uuid"},"due_at":{"type":"string","nullable":true,"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"assignee_user_id":{"type":"string","nullable":true,"format":"uuid"}},"required":["id","title","status","priority","project_id","due_at","created_at","assignee_user_id"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/counsel/{workspaceId}/quotes":{"get":{"tags":["Counsel"],"summary":"List quotes","description":"Liste les devis (quotes) du workspace.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"contact_id":{"type":"string","nullable":true,"format":"uuid"},"status":{"type":"string"},"amount_cents":{"type":"integer","minimum":0},"currency":{"type":"string","minLength":3,"maxLength":3},"issued_at":{"type":"string","format":"date-time"},"expires_at":{"type":"string","nullable":true,"format":"date-time"}},"required":["id","contact_id","status","amount_cents","currency","issued_at","expires_at"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/counsel/{workspaceId}/invoices":{"get":{"tags":["Counsel"],"summary":"List invoices","description":"Liste les factures du workspace.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"contact_id":{"type":"string","nullable":true,"format":"uuid"},"status":{"type":"string"},"amount_cents":{"type":"integer","minimum":0},"currency":{"type":"string","minLength":3,"maxLength":3},"issue_date":{"type":"string","format":"date-time"},"due_date":{"type":"string","nullable":true,"format":"date-time"}},"required":["id","contact_id","status","amount_cents","currency","issue_date","due_date"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/studio/{workspaceId}/drafts":{"get":{"tags":["Studio"],"summary":"List content drafts","description":"Liste les drafts (contenu marketing multi-canal) du workspace. Filtres status, target_platform.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string"},"required":false,"name":"target_platform","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"status":{"type":"string"},"target_platform":{"type":"string","nullable":true},"publish_approved_at":{"type":"string","nullable":true,"format":"date-time"},"created_at":{"type":"string","format":"date-time"},"scheduled_at":{"type":"string","nullable":true,"format":"date-time"}},"required":["id","title","status","target_platform","publish_approved_at","created_at","scheduled_at"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/inbox/{workspaceId}/threads":{"get":{"tags":["Inbox"],"summary":"List inbox threads","description":"Liste les threads DM unifié (Instagram, LinkedIn, WhatsApp, etc.). Filtres : channel, status, limit.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"channel","in":"query"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"channel":{"type":"string"},"contact_id":{"type":"string","nullable":true,"format":"uuid"},"last_message_at":{"type":"string","nullable":true,"format":"date-time"},"status":{"type":"string"},"unread_count":{"type":"integer","minimum":0}},"required":["id","channel","contact_id","last_message_at","status","unread_count"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/analytics/{workspaceId}/summary":{"get":{"tags":["Analytics"],"summary":"Get workspace analytics summary","description":"Snapshot agrégé du workspace sur les N derniers jours (default 7) : new_contacts, new_deals, new_drafts, new_bookings, invoiced_cents.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":365},"required":false,"name":"days","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"window_days":{"type":"integer","minimum":0,"exclusiveMinimum":true},"new_contacts":{"type":"integer","minimum":0},"new_deals":{"type":"integer","minimum":0},"new_drafts":{"type":"integer","minimum":0},"new_bookings":{"type":"integer","minimum":0},"invoices_count":{"type":"integer","minimum":0},"invoiced_cents":{"type":"integer","minimum":0}},"required":["window_days","new_contacts","new_deals","new_drafts","new_bookings","invoices_count","invoiced_cents"]}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/ads/{workspaceId}/campaigns":{"get":{"tags":["Ads"],"summary":"List ad campaigns","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workspaceId","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"status":{"type":"string"},"objective":{"type":"string","nullable":true},"budget_cents":{"type":"integer","nullable":true,"minimum":0},"created_at":{"type":"string","format":"date-time"}},"required":["id","name","status","objective","budget_cents","created_at"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/voice/{workspaceId}/calls":{"get":{"tags":["Voice"],"summary":"List voice calls","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"prospect_id","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"direction":{"type":"string"},"status":{"type":"string"},"duration_seconds":{"type":"integer","nullable":true,"minimum":0},"prospect_id":{"type":"string","nullable":true,"format":"uuid"},"from_e164":{"type":"string","nullable":true},"to_e164":{"type":"string","nullable":true}},"required":["id","workspace_id","direction","status","duration_seconds","prospect_id","from_e164","to_e164"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/pages/{workspaceId}":{"get":{"tags":["Pages"],"summary":"List pages (page builder)","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"string"},"required":false,"name":"status","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":500},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"slug":{"type":"string","minLength":1,"maxLength":80,"pattern":"^[a-z0-9]+(?:-[a-z0-9]+)*$"},"title":{"type":"string"},"status":{"type":"string"},"published_at":{"type":"string","nullable":true,"format":"date-time"},"updated_at":{"type":"string","format":"date-time"}},"required":["id","slug","title","status","published_at","updated_at"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/media/{workspaceId}":{"get":{"tags":["Media"],"summary":"List media items","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workspaceId","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":200},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"bucket":{"type":"string"},"storage_path":{"type":"string"},"mime_type":{"type":"string"},"size_bytes":{"type":"integer","nullable":true,"minimum":0},"width":{"type":"integer","nullable":true,"minimum":0},"height":{"type":"integer","nullable":true,"minimum":0}},"required":["id","bucket","storage_path","mime_type","size_bytes","width","height"]}},"pagination":{"type":"object","properties":{"next_cursor":{"type":"string","nullable":true},"has_more":{"type":"boolean"}},"required":["next_cursor","has_more"]}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/auth/session":{"post":{"tags":["Auth"],"summary":"Validate session token + optional device registration","description":"Endpoint mobile : le client envoie son Supabase JWT en Authorization Bearer. L'API valide et retourne user_id + ttl restant. Optionnel : device_id/device_label pour push notifications futures.","security":[{"bearerAuth":[]}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"device_id":{"type":"string","minLength":1,"maxLength":200},"device_label":{"type":"string","minLength":1,"maxLength":200}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"user_id":{"type":"string"},"issued_at":{"type":"string","format":"date-time"},"expires_in_seconds":{"type":"integer","nullable":true,"minimum":0,"exclusiveMinimum":true}},"required":["user_id","issued_at","expires_in_seconds"]}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/api-keys":{"get":{"tags":["API Keys"],"summary":"List my API keys","description":"Liste les API keys du workspace courant. Le plaintext token n est jamais retourne, juste les 16 premiers caracteres (prefix).","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"created_by_user_id":{"type":"string","nullable":true,"format":"uuid"},"name":{"type":"string","minLength":1,"maxLength":80},"prefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"expires_at":{"type":"string","nullable":true,"format":"date-time"},"last_used_at":{"type":"string","nullable":true,"format":"date-time"},"revoked_at":{"type":"string","nullable":true,"format":"date-time"},"created_at":{"type":"string","format":"date-time"}},"required":["id","workspace_id","created_by_user_id","name","prefix","scopes","expires_at","last_used_at","revoked_at","created_at"]}}},"required":["data"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}},"post":{"tags":["API Keys"],"summary":"Create an API key","description":"Cree une API key scopee au workspace courant. Le plaintext token est retourne UNE SEULE FOIS dans la response (champ token). Stocke-le immediatement.","security":[{"bearerAuth":[]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":80},"scopes":{"type":"array","items":{"type":"string","minLength":1,"pattern":"^(\\*|[a-z]+:(\\*|[a-z][a-z0-9_]*))$"},"minItems":1,"maxItems":20},"expires_at":{"type":"string","nullable":true,"format":"date-time"}},"required":["name"]}}}},"responses":{"201":{"description":"Created","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"workspace_id":{"type":"string","format":"uuid"},"created_by_user_id":{"type":"string","nullable":true,"format":"uuid"},"name":{"type":"string","minLength":1,"maxLength":80},"prefix":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}},"expires_at":{"type":"string","nullable":true,"format":"date-time"},"last_used_at":{"type":"string","nullable":true,"format":"date-time"},"revoked_at":{"type":"string","nullable":true,"format":"date-time"},"created_at":{"type":"string","format":"date-time"}},"required":["id","workspace_id","created_by_user_id","name","prefix","scopes","expires_at","last_used_at","revoked_at","created_at"]},"token":{"type":"string"}},"required":["data","token"]}}}},"400":{"description":"Bad request","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}},"/api-keys/{id}":{"delete":{"tags":["API Keys"],"summary":"Revoke an API key","description":"Revoke une API key (revoked_at = now). Idempotent : revoque deja-revoquee retourne revoked=false.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"revoked":{"type":"boolean"}},"required":["revoked"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}},"403":{"description":"Forbidden","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","enum":["BAD_REQUEST","UNAUTHORIZED","FORBIDDEN","NOT_FOUND","CONFLICT","UNPROCESSABLE","RATE_LIMITED","INTERNAL"]},"message":{"type":"string"},"details":{"type":"object","additionalProperties":{"nullable":true}},"request_id":{"type":"string"}},"required":["code","message"]}},"required":["error"]}}}}}}}}}