{"openapi":"3.1.0","info":{"title":"Owlic API","version":"1.0.0","description":"Public API for Owlic. Authenticate with an organization API key (`owlic_sk_…`) via the `Authorization: Bearer` or `X-Api-Key` header. The business API is served from https://api.owlic.fr/v1."},"servers":[{"url":"https://api.owlic.fr","description":"Production"}],"tags":[{"name":"Identity","description":"Identify the calling API key."},{"name":"Trainers","description":"Trainers in the organization."},{"name":"Training Programs","description":"Training programs and their modules."},{"name":"Training Actions","description":"Training actions and the Qualiopi workflow: needs analysis, beneficiaries, program, sessions, trainers, pricing, and convention."},{"name":"System","description":"Liveness and readiness probes."},{"name":"Authentication","description":"Better Auth endpoints (served from the app domain)."}],"components":{"securitySchemes":{"apiKeyCookie":{"type":"apiKey","in":"cookie","name":"apiKeyCookie","description":"API Key authentication via cookie"},"bearerAuth":{"type":"http","scheme":"bearer","description":"Bearer token authentication"},"ApiKeyAuth":{"type":"http","scheme":"bearer","description":"Owlic API key (format `owlic_sk_…`). Send it as `Authorization: Bearer <key>` or the `X-Api-Key` header."}},"schemas":{"User":{"type":"object","properties":{"id":{"type":"string","readOnly":true},"name":{"type":"string"},"email":{"type":"string"},"emailVerified":{"type":"boolean","default":false,"readOnly":true},"image":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","name","email","emailVerified","createdAt","updatedAt"]},"Session":{"type":"object","properties":{"id":{"type":"string","readOnly":true},"expiresAt":{"type":"string","format":"date-time"},"token":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"ipAddress":{"type":"string"},"userAgent":{"type":"string"},"userId":{"type":"string"}},"required":["id","expiresAt","token","createdAt","updatedAt","userId"]},"Account":{"type":"object","properties":{"id":{"type":"string","readOnly":true},"accountId":{"type":"string"},"providerId":{"type":"string"},"userId":{"type":"string"},"accessToken":{"type":"string"},"refreshToken":{"type":"string"},"idToken":{"type":"string"},"accessTokenExpiresAt":{"type":"string","format":"date-time"},"refreshTokenExpiresAt":{"type":"string","format":"date-time"},"scope":{"type":"string"},"password":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","accountId","providerId","userId","createdAt","updatedAt"]},"Verification":{"type":"object","properties":{"id":{"type":"string","readOnly":true},"identifier":{"type":"string"},"value":{"type":"string"},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","identifier","value","expiresAt","createdAt","updatedAt"]},"Apikey":{"type":"object","properties":{"id":{"type":"string","readOnly":true},"configId":{"type":"string","default":"default","readOnly":true},"name":{"type":"string","readOnly":true},"start":{"type":"string","readOnly":true},"referenceId":{"type":"string","readOnly":true},"prefix":{"type":"string","readOnly":true},"key":{"type":"string","readOnly":true},"refillInterval":{"type":"number","readOnly":true},"refillAmount":{"type":"number","readOnly":true},"lastRefillAt":{"type":"string","format":"date-time","readOnly":true},"enabled":{"type":"boolean","default":true,"readOnly":true},"rateLimitEnabled":{"type":"boolean","default":true,"readOnly":true},"rateLimitTimeWindow":{"type":"number","default":3600000,"readOnly":true},"rateLimitMax":{"type":"number","default":1000,"readOnly":true},"requestCount":{"type":"number","default":0,"readOnly":true},"remaining":{"type":"number","readOnly":true},"lastRequest":{"type":"string","format":"date-time","readOnly":true},"expiresAt":{"type":"string","format":"date-time","readOnly":true},"createdAt":{"type":"string","format":"date-time","readOnly":true},"updatedAt":{"type":"string","format":"date-time","readOnly":true},"permissions":{"type":"string","readOnly":true},"metadata":{"type":"string"}},"required":["id","configId","referenceId","key","createdAt","updatedAt"]},"WhoAmI":{"type":"object","properties":{"authenticated":{"type":"boolean","enum":[true]},"organizationId":{"type":"string","example":"org_abc123"},"userId":{"type":"string"},"apiKeyId":{"type":"string"}},"required":["authenticated","organizationId","userId","apiKeyId"]},"ErrorResponse":{"type":"object","properties":{"error":{"type":"object","properties":{"code":{"type":"string","example":"MISSING_API_KEY"},"message":{"type":"string","example":"Provide an API key via 'Authorization: Bearer <key>' or 'X-Api-Key'."}},"required":["code","message"]}},"required":["error"]},"Trainer":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":["string","null"]},"type":{"type":"string","description":"Trainer type","example":"internal"},"status":{"type":"string","description":"Trainer status","example":"active"},"specializations":{"type":"array","items":{"type":"string"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","firstName","lastName","email","phone","type","status","specializations","createdAt","updatedAt"]},"TrainerDetail":{"allOf":[{"$ref":"#/components/schemas/Trainer"},{"type":"object","properties":{"profile":{"type":"object","properties":{"bio":{"type":["string","null"]},"expertise":{"type":"array","items":{"type":"string"}},"experienceYears":{"type":["number","null"]}},"required":["bio","expertise","experienceYears"]}},"required":["profile"]}]},"TrainingAction":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"status":{"type":"string","description":"Training action status","example":"draft"},"startDate":{"type":["string","null"],"format":"date-time"},"endDate":{"type":["string","null"],"format":"date-time"},"trainingProgramId":{"type":["string","null"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","title","status","startDate","endDate","trainingProgramId","createdAt","updatedAt"]},"AssignedTrainer":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"type":{"type":"string","enum":["internal","external"]},"email":{"type":"string"},"phone":{"type":["string","null"]},"invitationStatus":{"type":["string","null"],"enum":["draft","sent","accepted","declined","expired","cancelled"]},"invitationDate":{"type":["string","null"],"format":"date-time"},"invitationSentAt":{"type":["string","null"],"format":"date-time"}},"required":["id","firstName","lastName","type","email","phone","invitationStatus","invitationDate","invitationSentAt"]},"BeneficiaryCompany":{"type":["object","null"],"properties":{"id":{"type":"string"},"name":{"type":"string"},"siret":{"type":["string","null"]},"siren":{"type":["string","null"]},"address":{"type":["string","null"]},"city":{"type":["string","null"]},"zipCode":{"type":["string","null"]},"contactEmail":{"type":["string","null"]},"contactPhone":{"type":["string","null"]},"website":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"administrativeContacts":{}},"required":["id","name","siret","siren","address","city","zipCode","contactEmail","contactPhone","website","createdAt","updatedAt"]},"TrainingActionBeneficiary":{"type":"object","properties":{"id":{"type":"string"},"trainingActionId":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string"},"phone":{"type":["string","null"]},"birthDate":{"type":["string","null"]},"birthPlace":{"type":["string","null"]},"address":{"type":["string","null"]},"companyId":{"type":["string","null"]},"company":{"$ref":"#/components/schemas/BeneficiaryCompany"}},"required":["id","trainingActionId","firstName","lastName","email","phone","birthDate","birthPlace","address","companyId","company"]},"PlannedSession":{"type":"object","properties":{"id":{"type":"string"},"date":{"type":"string","description":"Session date (YYYY-MM-DD)","example":"2026-07-01"},"trainingType":{"type":"string","example":"presentiel"},"location":{"type":["string","null"]},"meetingUrl":{"type":["string","null"]},"totalHours":{"type":"number"},"morning":{"type":"object","properties":{"enabled":{"type":"boolean"},"startTime":{"type":"string"},"endTime":{"type":"string"}},"required":["enabled","startTime","endTime"]},"afternoon":{"type":"object","properties":{"enabled":{"type":"boolean"},"startTime":{"type":"string"},"endTime":{"type":"string"}},"required":["enabled","startTime","endTime"]}},"required":["id","date","trainingType","location","meetingUrl","totalHours","morning","afternoon"]},"SavedNeedsAnalysis":{"type":["object","null"],"properties":{"id":{"type":"string"},"interestedProgram":{"type":"string"},"trainingObjectives":{"type":"array","items":{"type":"string"}},"concreteApplications":{"type":"string"},"improvementPoints":{"type":"string"},"specificNeeds":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","interestedProgram","trainingObjectives","concreteApplications","improvementPoints","specificNeeds","createdAt","updatedAt"]},"ConventionsStatus":{"type":"object","properties":{"hasConventions":{"type":"boolean"},"conventionCount":{"type":"integer"},"areAllSigned":{"type":"boolean"},"pendingSignatureCount":{"type":"integer"}},"required":["hasConventions","conventionCount","areAllSigned","pendingSignatureCount"]},"TrainingActionDetail":{"allOf":[{"$ref":"#/components/schemas/TrainingAction"},{"type":"object","properties":{"description":{"type":["string","null"]},"organizationId":{"type":"string"},"maxParticipants":{"type":["integer","null"]},"totalBudget":{"type":["number","null"]},"requiresQualiopiCompliance":{"type":"boolean"},"qualiopiFolderId":{"type":["string","null"]},"trainers":{"type":"array","items":{"$ref":"#/components/schemas/AssignedTrainer"}},"beneficiaries":{"type":"array","items":{"$ref":"#/components/schemas/TrainingActionBeneficiary"}},"sessions":{"type":"array","items":{"$ref":"#/components/schemas/PlannedSession"}},"needsAnalysis":{"$ref":"#/components/schemas/SavedNeedsAnalysis"},"conventionsStatus":{"$ref":"#/components/schemas/ConventionsStatus"}},"required":["description","organizationId","maxParticipants","totalBudget","requiresQualiopiCompliance","qualiopiFolderId","trainers","beneficiaries","sessions","needsAnalysis","conventionsStatus"]}]},"TrainingProgram":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":"string"},"modulesCount":{"type":"integer"},"totalDuration":{"type":"number","description":"Total duration in minutes"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","title","modulesCount","totalDuration","createdAt","updatedAt"]},"Pagination":{"type":"object","properties":{"page":{"type":"integer"},"limit":{"type":"integer"},"total":{"type":"integer"},"totalPages":{"type":"integer"}},"required":["page","limit","total","totalPages"]},"TrainingProgramModule":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"duration":{"type":"number","description":"Module duration in minutes"},"order":{"type":"integer"}},"required":["id","name","duration","order"]},"TrainingProgramDetail":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":["string","null"]},"objectives":{"type":"array","items":{"type":"string"}},"prerequisites":{"type":["string","null"]},"modulesCount":{"type":"integer"},"totalDuration":{"type":"number","description":"Total duration in minutes"},"modules":{"type":"array","items":{"$ref":"#/components/schemas/TrainingProgramModule"}},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","title","description","objectives","prerequisites","modulesCount","totalDuration","modules","createdAt","updatedAt"]},"TrainingActionRecord":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":["string","null"]},"trainingProgramId":{"type":["string","null"]},"organizationId":{"type":"string"},"startDate":{"type":["string","null"],"format":"date-time"},"endDate":{"type":["string","null"],"format":"date-time"},"maxParticipants":{"type":["integer","null"]},"totalBudget":{"type":["number","null"]},"fundingSourceId":{"type":["string","null"]},"status":{"type":"string","example":"draft"},"requiresQualiopiCompliance":{"type":"boolean"},"qualiopiFolderId":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","title","description","trainingProgramId","organizationId","startDate","endDate","maxParticipants","totalBudget","fundingSourceId","status","requiresQualiopiCompliance","qualiopiFolderId","createdAt","updatedAt"]},"CreateTrainingActionRequest":{"type":"object","properties":{"title":{"type":"string","minLength":2,"maxLength":255,"example":"Formation Excel avancé"},"description":{"type":"string","maxLength":500},"requiresQualiopiCompliance":{"type":"boolean","example":false}},"required":["title","requiresQualiopiCompliance"]},"NeedsAnalysisRequest":{"type":"object","properties":{"interestedProgram":{"type":"string","minLength":1,"maxLength":255},"trainingObjectives":{"type":"array","items":{"type":"string","maxLength":500},"minItems":1,"maxItems":20},"concreteApplications":{"type":"string","minLength":1,"maxLength":2000},"improvementPoints":{"type":"string","minLength":1,"maxLength":2000},"specificNeeds":{"type":["string","null"],"maxLength":2000}},"required":["interestedProgram","trainingObjectives","concreteApplications","improvementPoints"]},"NeedsAnalysisSaved":{"type":"object","properties":{"id":{"type":"string"},"trainingActionId":{"type":"string"},"needsAnalysis":{"$ref":"#/components/schemas/NeedsAnalysisRequest"},"savedAt":{"type":"string","format":"date-time"}},"required":["id","trainingActionId","needsAnalysis","savedAt"]},"SaveBeneficiariesResult":{"type":"object","properties":{"beneficiariesSaved":{"type":"integer","example":1}},"required":["beneficiariesSaved"]},"BeneficiaryInput":{"type":"object","properties":{"firstName":{"type":"string","example":"Florian"},"lastName":{"type":"string","example":"Truchot"},"email":{"type":"string","format":"email","example":"support@owlic.fr"},"birthDate":{"type":"string"},"birthPlace":{"type":"string"},"companySiret":{"type":"string","description":"SIRET of this beneficiary's employer. The SAME SIRET MUST also appear in the top-level `companies[]` array; the API creates-or-looks-up the company by SIRET and links this beneficiary to it. Omit for an individual learner with no company.","example":"99499860700018"},"companyId":{"type":"string","description":"Legacy alias for `companySiret` — also holds a **SIRET**, not a company UUID. Prefer `companySiret`; if both are set, `companySiret` wins.","example":"99499860700018"},"phone":{"type":"string"},"hasSpecificNeeds":{"type":"boolean"},"specificNeeds":{"type":"string"}},"required":["firstName","lastName","email"]},"CompanyInput":{"type":"object","properties":{"siret":{"type":"string","description":"SIRET — the key a beneficiary references (via `companySiret`/`companyId`) to be linked to this company.","example":"99499860700018"},"denominationSociale":{"type":"string","example":"OWLIC"},"ville":{"type":"string","example":"Lyon"},"codePostal":{"type":"string","example":"69001"}},"required":["siret","denominationSociale","ville","codePostal"]},"SaveBeneficiariesRequest":{"type":"object","properties":{"beneficiaries":{"type":"array","items":{"$ref":"#/components/schemas/BeneficiaryInput"}},"companies":{"type":"array","items":{"$ref":"#/components/schemas/CompanyInput"},"description":"Companies referenced by beneficiaries, one entry per SIRET. Each is created (or matched if it already exists) by SIRET, then linked to every beneficiary whose `companySiret`/`companyId` equals that SIRET. A SIRET referenced by a beneficiary but missing here is rejected with 400."},"replaceExisting":{"type":"boolean","description":"If true, deletes ALL current beneficiaries of the action before saving these (makes re-runs idempotent). Companies are never duplicated (matched by SIRET)."}},"required":["beneficiaries"],"description":"Save the beneficiaries of a training action. To attach a beneficiary to a company, set their `companySiret` to the company SIRET AND include that company in `companies[]`. Linking is by SIRET — not by array order.","example":{"beneficiaries":[{"firstName":"Florian","lastName":"Truchot","email":"support@owlic.fr","companySiret":"99499860700018"}],"companies":[{"siret":"99499860700018","denominationSociale":"OWLIC","ville":"Lyon","codePostal":"69001"}],"replaceExisting":true}},"AssignProgramRequest":{"type":"object","properties":{"trainingProgramId":{"type":"string"}},"required":["trainingProgramId"]},"PlanSessionsResult":{"type":"object","properties":{"totalSessions":{"type":"integer","example":1},"totalHours":{"type":"number","example":7}},"required":["totalSessions","totalHours"]},"TimeSlot":{"type":"object","properties":{"enabled":{"type":"boolean"},"startTime":{"type":"string","example":"09:00"},"endTime":{"type":"string","example":"12:00"}},"required":["enabled","startTime","endTime"]},"SessionInput":{"type":"object","properties":{"date":{"type":"string","example":"2026-07-01"},"trainingType":{"type":"string","enum":["presentiel","distance","hybride"]},"address":{"type":"string"},"morning":{"$ref":"#/components/schemas/TimeSlot"},"afternoon":{"$ref":"#/components/schemas/TimeSlot"}},"required":["date","trainingType","morning","afternoon"]},"PlanSessionsRequest":{"type":"object","properties":{"sessions":{"type":"array","items":{"$ref":"#/components/schemas/SessionInput"}}},"required":["sessions"]},"InviteTrainersResult":{"type":"object","properties":{"trainersSaved":{"type":"integer"},"trainers":{"type":"array","items":{"type":"object","additionalProperties":{}}},"emailsEnabled":{"type":"boolean"},"trainersCompleted":{"type":"boolean"},"invitationsSent":{"type":"integer"},"emailsSent":{"type":"integer"},"emailFailures":{"type":"array","items":{"type":"object","properties":{"email":{"type":"string"},"error":{"type":"string"}},"required":["email","error"]}}},"required":["trainersSaved","trainers","emailsEnabled","trainersCompleted"]},"TrainerInput":{"type":"object","properties":{"id":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"type":{"type":"string","enum":["internal","external"]},"email":{"type":"string","format":"email"},"specialties":{"type":"array","items":{"type":"string"}},"certifications":{"type":"array","items":{"type":"string"}}},"required":["firstName","lastName","type"]},"InviteTrainersRequest":{"type":"object","properties":{"trainers":{"type":"array","items":{"$ref":"#/components/schemas/TrainerInput"},"maxItems":100},"sendInvitationEmails":{"type":"boolean","description":"Send invitation emails (default false)"},"responseDeadlineDays":{"type":"integer","description":"Response deadline in days (default 7)"}},"required":["trainers"]},"Expense":{"type":"object","properties":{"id":{"type":"string"},"label":{"type":"string","maxLength":200},"type":{"type":"string","enum":["training","travel","accommodation","meal","other"]},"amount":{"type":"number","minimum":0},"description":{"type":"string","maxLength":500}},"required":["label","type","amount"]},"PricingData":{"type":"object","properties":{"expenses":{"type":"array","items":{"$ref":"#/components/schemas/Expense"},"description":"At least one expense of type `training` is required."},"totalAmount":{"type":"number"}},"required":["expenses"]},"SetPricingRequest":{"type":"object","properties":{"pricingData":{"$ref":"#/components/schemas/PricingData"},"trainingProgramPrice":{"type":"number"},"trainingProgramTitle":{"type":"string"}},"required":["pricingData"]},"ConventionResult":{"type":"object","properties":{"conventionId":{"type":"string"},"conventionNumber":{"type":"string"},"content":{"type":"string"},"status":{"type":"string"}},"required":["conventionId","conventionNumber","content","status"]},"CustomClause":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string","minLength":1,"maxLength":255},"content":{"type":"string","minLength":1,"maxLength":5000},"mandatory":{"type":"boolean"},"order":{"type":"integer","minimum":0}},"required":["title","content","order"]},"GenerateConventionRequest":{"type":"object","properties":{"templateId":{"type":"string","format":"uuid"},"beneficiaryIds":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":50},"conventionTitle":{"type":"string","minLength":1,"maxLength":200},"useCustomClauses":{"type":"boolean"},"customClauses":{"type":"array","items":{"$ref":"#/components/schemas/CustomClause"}},"generatePdf":{"type":"boolean"},"sendNotifications":{"type":"boolean"},"metadata":{"type":"object","additionalProperties":{}}},"required":["templateId","beneficiaryIds","conventionTitle","useCustomClauses","generatePdf","sendNotifications"]},"CreateTrainingProgramResult":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":["string","null"]},"modulesCount":{"type":"integer"},"totalDuration":{"type":"number","description":"Total duration in minutes"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","title","description","modulesCount","totalDuration","createdAt"]},"DistributionChannels":{"type":"object","properties":{"website":{"type":"boolean"},"brochures":{"type":"boolean"},"socialNetworks":{"type":"boolean"},"tradeShow":{"type":"boolean"},"other":{"type":"boolean"}},"required":["website","brochures","socialNetworks","tradeShow","other"]},"DistributionUrls":{"type":"object","properties":{"website":{"type":"string","maxLength":2000},"brochures":{"type":"string","maxLength":2000},"socialNetworks":{"type":"string","maxLength":2000},"tradeShow":{"type":"string","maxLength":2000},"other":{"type":"string","maxLength":2000}}},"CreateTrainingProgramRequest":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":255,"example":"Formation Excel avancé"},"description":{"type":"string","maxLength":5000},"priceExcludingTax":{"type":"number","minimum":0},"objectives":{"type":"array","items":{"type":"string","maxLength":500},"maxItems":50},"prerequisites":{"type":"string","maxLength":5000},"distributionChannels":{"$ref":"#/components/schemas/DistributionChannels"},"distributionUrls":{"$ref":"#/components/schemas/DistributionUrls"}},"required":["title"]},"TrainingProgramCoreResult":{"type":"object","properties":{"id":{"type":"string"},"title":{"type":"string"},"description":{"type":["string","null"]},"prerequisites":{"type":["string","null"]},"objectives":{"type":"array","items":{"type":"string"}},"priceExcludingTax":{"type":["number","null"]},"distributionChannels":{"$ref":"#/components/schemas/DistributionChannels"},"distributionUrls":{"$ref":"#/components/schemas/DistributionUrls"},"positioningQuestionnaireUrl":{"type":["string","null"]},"evaluationExternalLink":{"type":["string","null"]}},"required":["id","title","description","prerequisites","objectives","priceExcludingTax","distributionChannels","distributionUrls","positioningQuestionnaireUrl","evaluationExternalLink"]},"UpdateTrainingProgramCoreRequest":{"type":"object","properties":{"title":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":5000},"priceExcludingTax":{"type":"number","minimum":0},"objectives":{"type":"array","items":{"type":"string","maxLength":500},"maxItems":50},"prerequisites":{"type":"string","maxLength":5000},"distributionChannels":{"allOf":[{"$ref":"#/components/schemas/DistributionChannels"},{"description":"Whole-value replace; omit BOTH distributionChannels and distributionUrls to leave the distribution unchanged."}]},"distributionUrls":{"allOf":[{"$ref":"#/components/schemas/DistributionUrls"},{"description":"Whole-value replace; omit BOTH distributionChannels and distributionUrls to leave the distribution unchanged."}]}}},"DeletedTrainingProgramResult":{"type":"object","properties":{"id":{"type":"string"},"deleted":{"type":"boolean","enum":[true]}},"required":["id","deleted"]},"TrainingProgramActivityResult":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"durationMinutes":{"type":"number","description":"Activity duration in minutes"}},"required":["id","name","description","durationMinutes"]},"TrainingProgramModuleResult":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":["string","null"]},"activities":{"type":"array","items":{"$ref":"#/components/schemas/TrainingProgramActivityResult"}}},"required":["id","name","description","activities"]},"TrainingProgramModulesResult":{"type":"object","properties":{"id":{"type":"string"},"modules":{"type":"array","items":{"$ref":"#/components/schemas/TrainingProgramModuleResult"}}},"required":["id","modules"]},"ProgramActivityInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":2000},"durationMinutes":{"type":"integer","exclusiveMinimum":0}},"required":["name","durationMinutes"]},"ProgramModuleInput":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":255},"description":{"type":"string","maxLength":2000},"activities":{"type":"array","items":{"$ref":"#/components/schemas/ProgramActivityInput"},"maxItems":100}},"required":["name","activities"]},"UpdateTrainingProgramModulesRequest":{"type":"object","properties":{"modules":{"type":"array","items":{"$ref":"#/components/schemas/ProgramModuleInput"},"maxItems":100,"description":"PUT = full replace of the program's module/activity tree."}},"required":["modules"]},"ProgramTrainersResult":{"type":"object","properties":{"programId":{"type":"string"},"trainerIds":{"type":"array","items":{"type":"string"}}},"required":["programId","trainerIds"]},"AddProgramTrainersRequest":{"type":"object","properties":{"trainerIds":{"type":"array","items":{"type":"string","format":"uuid"},"minItems":1,"maxItems":100}},"required":["trainerIds"]},"TrainingProgramPositioningResult":{"type":"object","properties":{"id":{"type":"string"},"positioningQuestionnaireUrl":{"type":["string","null"]}},"required":["id","positioningQuestionnaireUrl"]},"UpdateTrainingProgramPositioningRequest":{"type":"object","properties":{"positioningQuestionnaireUrl":{"type":"string","maxLength":2000,"description":"Send \"\" (empty string) to clear the questionnaire URL."}}},"TrainingProgramEvaluationResult":{"type":"object","properties":{"id":{"type":"string"},"evaluationExternalLink":{"type":["string","null"]}},"required":["id","evaluationExternalLink"]},"UpdateTrainingProgramEvaluationRequest":{"type":"object","properties":{"evaluationExternalLink":{"type":"string","maxLength":2000,"description":"Send \"\" (empty string) to clear the evaluation link."}}},"Health":{"type":"object","properties":{"status":{"type":"string","example":"ok"},"service":{"type":"string","example":"@owlic/api"},"surface":{"type":"string","example":"public"},"database":{"type":"string","example":"connected"},"timestamp":{"type":"string","format":"date-time"},"version":{"type":"string","example":"unknown"},"environment":{"type":"string","example":"production"}},"required":["status","service","surface","database","timestamp","version","environment"]}},"parameters":{}},"paths":{"/v1/whoami":{"get":{"tags":["Identity"],"summary":"Identify the calling API key","description":"Returns the organization and key bound to the request — useful to test authentication.","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"The authenticated key context","content":{"application/json":{"schema":{"$ref":"#/components/schemas/WhoAmI"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/trainers":{"get":{"tags":["Trainers"],"summary":"List trainers","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Trainers in the organization","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Trainer"}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/trainers/{trainerId}":{"get":{"tags":["Trainers"],"summary":"Get a trainer by id","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"trainerId","in":"path"}],"responses":{"200":{"description":"The trainer, with profile","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TrainerDetail"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-actions":{"get":{"tags":["Training Actions"],"summary":"List training actions","security":[{"ApiKeyAuth":[]}],"responses":{"200":{"description":"Training actions in the organization","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TrainingAction"}}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Training Actions"],"summary":"Create a training action","description":"Creates a training action for the calling key's organization. `organizationId` is taken from the API key and must not appear in the body. When `requiresQualiopiCompliance` is true, an associated Qualiopi folder is created.","security":[{"ApiKeyAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTrainingActionRequest"}}}},"responses":{"201":{"description":"The created training action","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TrainingActionRecord"}},"required":["data"]}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The operation was rejected by a domain rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-actions/{actionId}":{"get":{"tags":["Training Actions"],"summary":"Get a training action by id","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"actionId","in":"path"}],"responses":{"200":{"description":"The training action","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TrainingActionDetail"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-programs":{"get":{"tags":["Training Programs"],"summary":"List training programs (paginated)","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"description":"Page number (default 1)","example":1},"required":false,"name":"page","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"description":"Items per page (default 20, max 100)","example":20},"required":false,"name":"limit","in":"query"}],"responses":{"200":{"description":"A page of training programs","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/TrainingProgram"}},"pagination":{"$ref":"#/components/schemas/Pagination"}},"required":["data","pagination"]}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Training Programs"],"summary":"Create a training program","description":"Creates a training program for the calling key's organization. `organizationId` is taken from the API key and must not appear in the body; modules are set separately via `PUT /v1/training-programs/{programId}/modules`.","security":[{"ApiKeyAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateTrainingProgramRequest"}}}},"responses":{"201":{"description":"The created training program","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CreateTrainingProgramResult"}},"required":["data"]}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The operation was rejected by a domain rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-programs/{programId}":{"get":{"tags":["Training Programs"],"summary":"Get a training program by id","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"programId","in":"path"}],"responses":{"200":{"description":"The training program, with modules","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TrainingProgramDetail"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"patch":{"tags":["Training Programs"],"summary":"Update a training program's core fields","description":"Partial update of the program's core fields (only the fields present in the body are changed). Distribution is whole-value replace: send BOTH `distributionChannels` and `distributionUrls` to replace them, or omit BOTH to leave the distribution unchanged. Scoped to the API key's organization; a program owned by another organization returns 404.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"programId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTrainingProgramCoreRequest"}}}},"responses":{"200":{"description":"The updated core fields","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TrainingProgramCoreResult"}},"required":["data"]}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The operation was rejected by a domain rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Training Programs"],"summary":"Delete a training program","description":"Deletes the program. Scoped to the API key's organization; a program owned by another organization returns 404.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"programId","in":"path"}],"responses":{"200":{"description":"The deleted program id","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/DeletedTrainingProgramResult"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The operation was rejected by a domain rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-actions/{actionId}/needs-analysis":{"post":{"tags":["Training Actions"],"summary":"Save the needs analysis","description":"Upserts the \"analyse des besoins\" of the action and bumps its `updatedAt`.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"actionId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NeedsAnalysisRequest"}}}},"responses":{"200":{"description":"The saved needs analysis","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/NeedsAnalysisSaved"}},"required":["data"]}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-actions/{actionId}/beneficiaries":{"post":{"tags":["Training Actions"],"summary":"Save beneficiaries","description":"Identify/save the beneficiaries of the action. Domain validation (required fields, duplicates, bulk limits) runs server-side.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"actionId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaveBeneficiariesRequest"}}}},"responses":{"200":{"description":"Number of beneficiaries saved","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/SaveBeneficiariesResult"}},"required":["data"]}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The operation was rejected by a domain rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-actions/{actionId}/program":{"post":{"tags":["Training Actions"],"summary":"Assign a training program","description":"Links an existing program to the action. Both must belong to the calling organization.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"actionId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AssignProgramRequest"}}}},"responses":{"200":{"description":"The updated training action","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TrainingAction"}},"required":["data"]}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-actions/{actionId}/sessions":{"post":{"tags":["Training Actions"],"summary":"Plan the training sessions","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"actionId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PlanSessionsRequest"}}}},"responses":{"200":{"description":"Session totals","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PlanSessionsResult"}},"required":["data"]}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-actions/{actionId}/trainers":{"post":{"tags":["Training Actions"],"summary":"Assign trainers (optionally invite)","description":"Atomically replaces the action's trainers; when `sendInvitationEmails` is true, sends their invitation emails (best-effort — a partial email failure does not fail the operation).","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"actionId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InviteTrainersRequest"}}}},"responses":{"200":{"description":"Saved trainers and invitation outcome","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/InviteTrainersResult"}},"required":["data"]}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The operation was rejected by a domain rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-actions/{actionId}/pricing":{"post":{"tags":["Training Actions"],"summary":"Set the pricing","description":"Defines the commercial offer. At least one expense of type `training` is required.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"actionId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SetPricingRequest"}}}},"responses":{"200":{"description":"The persisted pricing","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/PricingData"}},"required":["data"]}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-actions/{actionId}/convention":{"post":{"tags":["Training Actions"],"summary":"Generate a convention","description":"Generates a \"convention de formation\" for the action.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"actionId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GenerateConventionRequest"}}}},"responses":{"201":{"description":"The generated convention","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ConventionResult"}},"required":["data"]}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Convention generation failed (e.g. unknown template).","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-programs/{programId}/modules":{"put":{"tags":["Training Programs"],"summary":"Replace the program's modules","description":"Full replace of the program's module/activity tree — the submitted `modules` array becomes the complete new tree. Scoped to the API key's organization; a program owned by another organization returns 404.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"programId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTrainingProgramModulesRequest"}}}},"responses":{"200":{"description":"The rebuilt module tree","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TrainingProgramModulesResult"}},"required":["data"]}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The operation was rejected by a domain rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-programs/{programId}/trainers":{"post":{"tags":["Training Programs"],"summary":"Add trainers to a program","description":"Associates the given trainers with the program. Scoped to the API key's organization; a program owned by another organization returns 404.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"programId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddProgramTrainersRequest"}}}},"responses":{"200":{"description":"The program's trainer ids after the change","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ProgramTrainersResult"}},"required":["data"]}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The operation was rejected by a domain rule.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-programs/{programId}/trainers/{trainerId}":{"delete":{"tags":["Training Programs"],"summary":"Remove a trainer from a program","description":"Removes the trainer's association with the program. Scoped to the API key's organization; a program owned by another organization returns 404.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"programId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"trainerId","in":"path"}],"responses":{"200":{"description":"The program's trainer ids after the change","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/ProgramTrainersResult"}},"required":["data"]}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-programs/{programId}/positioning":{"patch":{"tags":["Training Programs"],"summary":"Set the positioning questionnaire URL","description":"Sets (or clears, by sending \"\") the program's positioning questionnaire URL. Scoped to the API key's organization; a program owned by another organization returns 404.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"programId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTrainingProgramPositioningRequest"}}}},"responses":{"200":{"description":"The updated positioning URL","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TrainingProgramPositioningResult"}},"required":["data"]}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/v1/training-programs/{programId}/evaluation":{"patch":{"tags":["Training Programs"],"summary":"Set the evaluation external link","description":"Sets (or clears, by sending \"\") the program's evaluation external link. Scoped to the API key's organization; a program owned by another organization returns 404.","security":[{"ApiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"programId","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateTrainingProgramEvaluationRequest"}}}},"responses":{"200":{"description":"The updated evaluation link","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/TrainingProgramEvaluationResult"}},"required":["data"]}}}},"400":{"description":"Invalid request body.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Key disabled/expired.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found in this organization.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Per-key rate limit or usage quota exceeded.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Internal server error.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/health":{"get":{"tags":["System"],"summary":"Health check — liveness + database readiness (open)","description":"Open endpoint (no API key). Returns 200 when the service is up and the database is reachable, and 503 when the database is unreachable. Used by orchestrator probes and uptime monitors.","security":[],"responses":{"200":{"description":"Service is up and the database is reachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}},"503":{"description":"The database is unreachable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Health"}}}}}}},"/api/auth/sign-in/social":{"post":{"tags":["Authentication"],"description":"Sign in with a social provider","operationId":"socialSignIn","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"callbackURL":{"type":"string","description":"Callback URL to redirect to after the user has signed in"},"newUserCallbackURL":{"type":"string"},"errorCallbackURL":{"type":"string","description":"Callback URL to redirect to if an error happens"},"provider":{"anyOf":[{"type":"string","enum":["apple","atlassian","cognito","discord","facebook","figma","github","microsoft","google","huggingface","slack","spotify","twitch","twitter","dropbox","kick","linear","linkedin","gitlab","tiktok","reddit","roblox","salesforce","vk","zoom","notion","kakao","naver","line","paybin","paypal","polar","railway","vercel","wechat"]},{"type":"string"}]},"disableRedirect":{"type":"boolean","description":"Disable automatic redirection to the provider. Useful for handling the redirection yourself"},"idToken":{"type":"object","properties":{"token":{"type":"string","description":"ID token from the provider"},"nonce":{"type":"string","description":"Nonce used to generate the token"},"accessToken":{"type":"string","description":"Access token from the provider"},"refreshToken":{"type":"string","description":"Refresh token from the provider"},"expiresAt":{"type":"number","description":"Expiry date of the token"},"user":{"type":"object","properties":{"name":{"type":"object","properties":{"firstName":{"type":"string"},"lastName":{"type":"string"}}},"email":{"type":"string"}},"description":"The user object from the provider. Only available for some providers like Apple."}},"required":["token"]},"scopes":{"type":"array","items":{"type":"string"},"description":"Array of scopes to request from the provider. This will override the default scopes passed."},"requestSignUp":{"type":"boolean","description":"Explicitly request sign-up. Useful when disableImplicitSignUp is true for this provider"},"loginHint":{"type":"string","description":"The login hint to use for the authorization code request"},"additionalData":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["provider"]}}}},"responses":{"200":{"description":"Success - Returns session details (idToken branch) or an authorize URL (redirect branch)","content":{"application/json":{"schema":{"type":"object","description":"Returns session details when idToken is provided, or an authorize URL otherwise","properties":{"token":{"type":"string"},"user":{"type":"object","$ref":"#/components/schemas/User"},"url":{"type":"string"},"redirect":{"type":"boolean"}},"required":["redirect"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/callback/{id}":{"get":{"tags":["Authentication"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]},"post":{"tags":["Authentication"],"security":[{"bearerAuth":[]}],"parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"code":{"type":"string"},"error":{"type":"string"},"device_id":{"type":"string"},"error_description":{"type":"string"},"state":{"type":"string"},"user":{"type":"string"}}}}}},"responses":{"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/get-session":{"get":{"tags":["Authentication"],"description":"Get the current session","operationId":"getSession","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":["object","null"],"properties":{"session":{"$ref":"#/components/schemas/Session"},"user":{"$ref":"#/components/schemas/User"}},"required":["session","user"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]},"post":{"tags":["Authentication"],"description":"Get the current session","operationId":"getSessionPost","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":["object","null"],"properties":{"session":{"$ref":"#/components/schemas/Session"},"user":{"$ref":"#/components/schemas/User"}},"required":["session","user"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/sign-out":{"post":{"tags":["Authentication"],"description":"Sign out the current user","operationId":"signOut","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}}}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/sign-up/email":{"post":{"tags":["Authentication"],"description":"Sign up a user using email and password","operationId":"signUpWithEmailAndPassword","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"The name of the user"},"email":{"type":"string","description":"The email of the user"},"password":{"type":"string","description":"The password of the user"},"image":{"type":"string","description":"The profile image URL of the user"},"callbackURL":{"type":"string","description":"The URL to use for email verification callback"},"rememberMe":{"type":"boolean","description":"If this is false, the session will not be remembered. Default is `true`."}},"required":["name","email","password"]}}}},"responses":{"200":{"description":"Successfully created user","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","nullable":true,"description":"Authentication token for the session"},"user":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of the user"},"email":{"type":"string","format":"email","description":"The email address of the user"},"name":{"type":"string","description":"The name of the user"},"image":{"type":"string","format":"uri","nullable":true,"description":"The profile image URL of the user"},"emailVerified":{"type":"boolean","description":"Whether the email has been verified"},"createdAt":{"type":"string","format":"date-time","description":"When the user was created"},"updatedAt":{"type":"string","format":"date-time","description":"When the user was last updated"}},"required":["id","email","name","emailVerified","createdAt","updatedAt"]}},"required":["user"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"422":{"description":"Unprocessable Entity. User already exists or failed to create user.","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/sign-in/email":{"post":{"tags":["Authentication"],"description":"Sign in with email and password","operationId":"signInEmail","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","description":"Email of the user"},"password":{"type":"string","description":"Password of the user"},"callbackURL":{"type":"string","description":"Callback URL to use as a redirect for email verification"},"rememberMe":{"type":"boolean","description":"If this is false, the session will not be remembered. Default is `true`."}},"required":["email","password"]}}}},"responses":{"200":{"description":"Success - Returns either session details or redirect URL","content":{"application/json":{"schema":{"type":"object","description":"Session response when idToken is provided","properties":{"redirect":{"type":"boolean","enum":[false]},"token":{"type":"string","description":"Session token"},"url":{"type":"string","nullable":true},"user":{"type":"object","$ref":"#/components/schemas/User"}},"required":["redirect","token","user"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/reset-password":{"post":{"tags":["Authentication"],"description":"Reset the password for a user","operationId":"resetPassword","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"newPassword":{"type":"string","description":"The new password to set"},"token":{"type":"string","description":"The token to reset the password"}},"required":["newPassword"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"boolean"}}}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/verify-password":{"post":{"tags":["Authentication"],"description":"Verify the current user's password","operationId":"verifyPassword","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"password":{"type":"string","description":"The password to verify"}},"required":["password"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"boolean"}}}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/verify-email":{"get":{"tags":["Authentication"],"description":"Verify the email of the user","security":[{"bearerAuth":[]}],"parameters":[{"name":"token","in":"query","description":"The token to verify the email","required":true,"schema":{"type":"string"}},{"name":"callbackURL","in":"query","description":"The URL to redirect to after email verification","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","$ref":"#/components/schemas/User"},"status":{"type":"boolean","description":"Indicates if the email was verified successfully"}},"required":["user","status"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/send-verification-email":{"post":{"tags":["Authentication"],"description":"Send a verification email to the user","operationId":"sendVerificationEmail","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","description":"The email to send the verification email to","example":"user@example.com"},"callbackURL":{"type":"string","description":"The URL to use for email verification callback","example":"https://example.com/callback","nullable":true}},"required":["email"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"boolean","description":"Indicates if the email was sent successfully","example":true}}}}}},"400":{"description":"Bad Request","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","description":"Error message","example":"Verification email isn't enabled"}}}}}},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/change-email":{"post":{"tags":["Authentication"],"operationId":"changeEmail","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"newEmail":{"type":"string","description":"The new email address to set must be a valid email address"},"callbackURL":{"type":"string","description":"The URL to redirect to after email verification"}},"required":["newEmail"]}}}},"responses":{"200":{"description":"Email change request processed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","$ref":"#/components/schemas/User"},"status":{"type":"boolean","description":"Indicates if the request was successful"},"message":{"type":"string","enum":["Email updated","Verification email sent"],"description":"Status message of the email change process","nullable":true}},"required":["status"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/change-password":{"post":{"tags":["Authentication"],"description":"Change the password of the user","operationId":"changePassword","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"newPassword":{"type":"string","description":"The new password to set"},"currentPassword":{"type":"string","description":"The current password is required"},"revokeOtherSessions":{"type":"boolean","description":"Must be a boolean value"}},"required":["newPassword","currentPassword"]}}}},"responses":{"200":{"description":"Password successfully changed","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","nullable":true,"description":"New session token if other sessions were revoked"},"user":{"type":"object","properties":{"id":{"type":"string","description":"The unique identifier of the user"},"email":{"type":"string","format":"email","description":"The email address of the user"},"name":{"type":"string","description":"The name of the user"},"image":{"type":"string","format":"uri","nullable":true,"description":"The profile image URL of the user"},"emailVerified":{"type":"boolean","description":"Whether the email has been verified"},"createdAt":{"type":"string","format":"date-time","description":"When the user was created"},"updatedAt":{"type":"string","format":"date-time","description":"When the user was last updated"}},"required":["id","email","name","emailVerified","createdAt","updatedAt"]}},"required":["user"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/update-session":{"post":{"tags":["Authentication"],"description":"Update the current session","operationId":"updateSession","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","propertyNames":{"type":"string","description":"Field name must be a string"},"additionalProperties":{}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"session":{"type":"object","$ref":"#/components/schemas/Session"}}}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/update-user":{"post":{"tags":["Authentication"],"description":"Update the current user","operationId":"updateUser","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","description":"The name of the user"},"image":{"type":"string","description":"The image of the user","nullable":true}}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","$ref":"#/components/schemas/User"}}}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/delete-user":{"post":{"tags":["Authentication"],"description":"Delete the user","operationId":"deleteUser","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"callbackURL":{"type":"string","description":"The callback URL to redirect to after the user is deleted"},"password":{"type":"string","description":"The user's password. Required if session is not fresh"},"token":{"type":"string","description":"The deletion verification token"}}}}}},"responses":{"200":{"description":"User deletion processed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","description":"Indicates if the operation was successful"},"message":{"type":"string","enum":["User deleted","Verification email sent"],"description":"Status message of the deletion process"}},"required":["success","message"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/request-password-reset":{"post":{"tags":["Authentication"],"description":"Send a password reset email to the user","operationId":"requestPasswordReset","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","description":"The email address of the user to send a password reset email to"},"redirectTo":{"type":"string","description":"The URL to redirect the user to reset their password. If the token isn't valid or expired, it'll be redirected with a query parameter `?error=INVALID_TOKEN`. If the token is valid, it'll be redirected with a query parameter `?token=VALID_TOKEN"}},"required":["email"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"boolean"},"message":{"type":"string"}}}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/reset-password/{token}":{"get":{"tags":["Authentication"],"description":"Redirects the user to the callback URL with the token","operationId":"resetPasswordCallback","security":[{"bearerAuth":[]}],"parameters":[{"name":"token","in":"path","required":true,"description":"The token to reset the password","schema":{"type":"string"}},{"name":"callbackURL","in":"query","required":true,"description":"The URL to redirect the user to reset their password","schema":{"type":"string"}}],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string"}}}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/list-sessions":{"get":{"tags":["Authentication"],"description":"List all active sessions for the user","operationId":"listUserSessions","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Session"}}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/revoke-session":{"post":{"tags":["Authentication"],"description":"Revoke a single session","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"token":{"type":"string","description":"The token to revoke"}},"required":["token"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"boolean","description":"Indicates if the session was revoked successfully"}},"required":["status"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/revoke-sessions":{"post":{"tags":["Authentication"],"description":"Revoke all sessions for the user","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"boolean","description":"Indicates if all sessions were revoked successfully"}},"required":["status"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/revoke-other-sessions":{"post":{"tags":["Authentication"],"description":"Revoke all other sessions for the user except the current one","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{}}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"boolean","description":"Indicates if all other sessions were revoked successfully"}},"required":["status"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/link-social":{"post":{"tags":["Authentication"],"description":"Link a social account to the user","operationId":"linkSocialAccount","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"callbackURL":{"type":"string","description":"The URL to redirect to after the user has signed in"},"provider":{"anyOf":[{"type":"string","enum":["apple","atlassian","cognito","discord","facebook","figma","github","microsoft","google","huggingface","slack","spotify","twitch","twitter","dropbox","kick","linear","linkedin","gitlab","tiktok","reddit","roblox","salesforce","vk","zoom","notion","kakao","naver","line","paybin","paypal","polar","railway","vercel","wechat"]},{"type":"string"}]},"idToken":{"type":"object","properties":{"token":{"type":"string"},"nonce":{"type":"string"},"accessToken":{"type":"string"},"refreshToken":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}}},"required":["token"]},"requestSignUp":{"type":"boolean"},"scopes":{"type":"array","items":{"type":"string"},"description":"Additional scopes to request from the provider"},"errorCallbackURL":{"type":"string","description":"The URL to redirect to if there is an error during the link process"},"disableRedirect":{"type":"boolean","description":"Disable automatic redirection to the provider. Useful for handling the redirection yourself"},"additionalData":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{}}},"required":["provider"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","description":"The authorization URL to redirect the user to"},"redirect":{"type":"boolean","description":"Indicates if the user should be redirected to the authorization URL"},"status":{"type":"boolean"}},"required":["redirect"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/list-accounts":{"get":{"tags":["Authentication"],"description":"List all accounts linked to the user","operationId":"listUserAccounts","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"providerId":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"accountId":{"type":"string"},"userId":{"type":"string"},"scopes":{"type":"array","items":{"type":"string"}}},"required":["id","providerId","createdAt","updatedAt","accountId","userId","scopes"]}}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/delete-user/callback":{"get":{"tags":["Authentication"],"description":"Callback to complete user deletion with verification token","security":[{"bearerAuth":[]}],"parameters":[{"name":"token","in":"query","schema":{"type":"string","description":"The token to verify the deletion request"}},{"name":"callbackURL","in":"query","schema":{"type":"string","description":"The URL to redirect to after deletion"}}],"responses":{"200":{"description":"User successfully deleted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","description":"Indicates if the deletion was successful"},"message":{"type":"string","enum":["User deleted"],"description":"Confirmation message"}},"required":["success","message"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/unlink-account":{"post":{"tags":["Authentication"],"description":"Unlink an account","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"providerId":{"type":"string"},"accountId":{"type":"string"}},"required":["providerId"]}}}},"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"boolean"}}}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/refresh-token":{"post":{"tags":["Authentication"],"description":"Refresh the access token using a refresh token","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"providerId":{"type":"string","description":"The provider ID for the OAuth provider"},"accountId":{"type":"string","description":"The account ID associated with the refresh token"},"userId":{"type":"string","description":"The user ID associated with the account"}},"required":["providerId"]}}}},"responses":{"200":{"description":"Access token refreshed successfully","content":{"application/json":{"schema":{"type":"object","properties":{"tokenType":{"type":"string"},"idToken":{"type":"string"},"accessToken":{"type":"string"},"refreshToken":{"type":"string"},"accessTokenExpiresAt":{"type":"string","format":"date-time"},"refreshTokenExpiresAt":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Invalid refresh token or provider configuration"},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/get-access-token":{"post":{"tags":["Authentication"],"description":"Get a valid access token, doing a refresh if needed","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"providerId":{"type":"string","description":"The provider ID for the OAuth provider"},"accountId":{"type":"string","description":"The account ID associated with the refresh token"},"userId":{"type":"string","description":"The user ID associated with the account"}},"required":["providerId"]}}}},"responses":{"200":{"description":"A Valid access token","content":{"application/json":{"schema":{"type":"object","properties":{"tokenType":{"type":"string"},"idToken":{"type":"string"},"accessToken":{"type":"string"},"accessTokenExpiresAt":{"type":"string","format":"date-time"}}}}}},"400":{"description":"Invalid refresh token or provider configuration"},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/account-info":{"get":{"tags":["Authentication"],"description":"Get the account info provided by the provider","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"application/json":{"schema":{"type":"object","properties":{"user":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"email":{"type":"string"},"image":{"type":"string"},"emailVerified":{"type":"boolean"}},"required":["id","emailVerified"]},"data":{"type":"object","properties":{},"additionalProperties":true}},"required":["user","data"],"additionalProperties":false}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/ok":{"get":{"tags":["Authentication"],"description":"Check if the API is working","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"API is working","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean","description":"Indicates if the API is working"}},"required":["ok"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/error":{"get":{"tags":["Authentication"],"description":"Displays an error page","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"Success","content":{"text/html":{"schema":{"type":"string","description":"The HTML content of the error page"}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/api-key/create":{"post":{"tags":["Authentication"],"description":"Create a new API key for a user","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"configId":{"type":"string","description":"The configuration ID to use for the API key. If not provided, the default configuration will be used."},"name":{"type":"string","description":"Name of the Api Key"},"expiresIn":{"type":["number","null"],"description":"Expiration time of the Api Key in seconds"},"prefix":{"type":"string","description":"Prefix of the Api Key"},"remaining":{"type":["number","null"],"description":"Remaining number of requests. Server side only"},"metadata":{},"refillAmount":{"type":"number","description":"Amount to refill the remaining count of the Api Key. server-only. Eg: 100"},"refillInterval":{"type":"number","description":"Interval to refill the Api Key in milliseconds. server-only. Eg: 1000"},"rateLimitTimeWindow":{"type":"number","description":"The duration in milliseconds where each request is counted. Once the `maxRequests` is reached, the request will be rejected until the `timeWindow` has passed, at which point the `timeWindow` will be reset. server-only. Eg: 1000"},"rateLimitMax":{"type":"number","description":"Maximum amount of requests allowed within a window. Once the `maxRequests` is reached, the request will be rejected until the `timeWindow` has passed, at which point the `timeWindow` will be reset. server-only. Eg: 100"},"rateLimitEnabled":{"type":"boolean","description":"Whether the key has rate limiting enabled. server-only. Eg: true"},"permissions":{"type":"object","propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"string"}},"description":"Permissions of the Api Key."},"userId":{"type":"string","description":"User Id of the user that the Api Key belongs to. server-only. Eg: \"user-id\""},"organizationId":{"type":"string","description":"Organization Id of the organization that the Api Key belongs to. Eg: 'org-id'"}}}}}},"responses":{"200":{"description":"API key created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"Unique identifier of the API key"},"createdAt":{"type":"string","format":"date-time","description":"Creation timestamp"},"updatedAt":{"type":"string","format":"date-time","description":"Last update timestamp"},"name":{"type":"string","nullable":true,"description":"Name of the API key"},"prefix":{"type":"string","nullable":true,"description":"Prefix of the API key"},"start":{"type":"string","nullable":true,"description":"Starting characters of the key (if configured)"},"key":{"type":"string","description":"The full API key (only returned on creation)"},"enabled":{"type":"boolean","description":"Whether the key is enabled"},"expiresAt":{"type":"string","format":"date-time","nullable":true,"description":"Expiration timestamp"},"referenceId":{"type":"string","description":"ID of the reference owning the key"},"lastRefillAt":{"type":"string","format":"date-time","nullable":true,"description":"Last refill timestamp"},"lastRequest":{"type":"string","format":"date-time","nullable":true,"description":"Last request timestamp"},"metadata":{"type":"object","nullable":true,"additionalProperties":true,"description":"Metadata associated with the key"},"rateLimitMax":{"type":"number","nullable":true,"description":"Maximum requests in time window"},"rateLimitTimeWindow":{"type":"number","nullable":true,"description":"Rate limit time window in milliseconds"},"remaining":{"type":"number","nullable":true,"description":"Remaining requests"},"refillAmount":{"type":"number","nullable":true,"description":"Amount to refill"},"refillInterval":{"type":"number","nullable":true,"description":"Refill interval in milliseconds"},"rateLimitEnabled":{"type":"boolean","description":"Whether rate limiting is enabled"},"requestCount":{"type":"number","description":"Current request count in window"},"permissions":{"type":"object","nullable":true,"additionalProperties":{"type":"array","items":{"type":"string"}},"description":"Permissions associated with the key"}},"required":["id","createdAt","updatedAt","key","enabled","referenceId","rateLimitEnabled","requestCount"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/api-key/get":{"get":{"tags":["Authentication"],"description":"Retrieve an existing API key by ID","security":[{"bearerAuth":[]}],"parameters":[{"name":"configId","in":"query","schema":{"type":"string","description":"The configuration ID to use for the API key lookup. If not provided, the default configuration will be used."}},{"name":"id","in":"query","schema":{"type":"string","description":"The id of the Api Key"}}],"responses":{"200":{"description":"API key retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"ID"},"name":{"type":"string","nullable":true,"description":"The name of the key"},"start":{"type":"string","nullable":true,"description":"Shows the first few characters of the API key, including the prefix. This allows you to show those few characters in the UI to make it easier for users to identify the API key."},"prefix":{"type":"string","nullable":true,"description":"The API Key prefix. Stored as plain text."},"userId":{"type":"string","description":"The owner of the user id"},"refillInterval":{"type":"number","nullable":true,"description":"The interval in milliseconds between refills of the `remaining` count. Example: 3600000 // refill every hour (3600000ms = 1h)"},"refillAmount":{"type":"number","nullable":true,"description":"The amount to refill"},"lastRefillAt":{"type":"string","format":"date-time","nullable":true,"description":"The last refill date"},"enabled":{"type":"boolean","description":"Sets if key is enabled or disabled","default":true},"rateLimitEnabled":{"type":"boolean","description":"Whether the key has rate limiting enabled"},"rateLimitTimeWindow":{"type":"number","nullable":true,"description":"The duration in milliseconds"},"rateLimitMax":{"type":"number","nullable":true,"description":"Maximum amount of requests allowed within a window"},"requestCount":{"type":"number","description":"The number of requests made within the rate limit time window"},"remaining":{"type":"number","nullable":true,"description":"Remaining requests (every time api key is used this should updated and should be updated on refill as well)"},"lastRequest":{"type":"string","format":"date-time","nullable":true,"description":"When last request occurred"},"expiresAt":{"type":"string","format":"date-time","nullable":true,"description":"Expiry date of a key"},"createdAt":{"type":"string","format":"date-time","description":"created at"},"updatedAt":{"type":"string","format":"date-time","description":"updated at"},"metadata":{"type":"object","nullable":true,"additionalProperties":true,"description":"Extra metadata about the apiKey"},"permissions":{"type":"string","nullable":true,"description":"Permissions for the api key (stored as JSON string)"}},"required":["id","userId","enabled","rateLimitEnabled","requestCount","createdAt","updatedAt"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/api-key/update":{"post":{"tags":["Authentication"],"description":"Update an existing API key by ID","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"configId":{"type":"string","description":"The configuration ID to use for the API key lookup. If not provided, the default configuration will be used."},"keyId":{"type":"string","description":"The id of the Api Key"},"userId":{"type":"string","description":"The id of the user which the api key belongs to. server-only. Eg: \"some-user-id\""},"name":{"type":"string","description":"The name of the key"},"enabled":{"type":"boolean","description":"Whether the Api Key is enabled or not"},"remaining":{"type":"number","description":"The number of remaining requests"},"refillAmount":{"type":"number","description":"The refill amount"},"refillInterval":{"type":"number","description":"The refill interval"},"metadata":{},"expiresIn":{"type":["number","null"],"description":"Expiration time of the Api Key in seconds"},"rateLimitEnabled":{"type":"boolean","description":"Whether the key has rate limiting enabled."},"rateLimitTimeWindow":{"type":"number","description":"The duration in milliseconds where each request is counted. server-only. Eg: 1000"},"rateLimitMax":{"type":"number","description":"Maximum amount of requests allowed within a window. Once the `maxRequests` is reached, the request will be rejected until the `timeWindow` has passed, at which point the `timeWindow` will be reset. server-only. Eg: 100"},"permissions":{"type":["object","null"],"propertyNames":{"type":"string"},"additionalProperties":{"type":"array","items":{"type":"string"}},"description":"Update the permissions on the API Key. server-only."}},"required":["keyId"]}}}},"responses":{"200":{"description":"API key updated successfully","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","description":"ID"},"name":{"type":"string","nullable":true,"description":"The name of the key"},"start":{"type":"string","nullable":true,"description":"Shows the first few characters of the API key, including the prefix. This allows you to show those few characters in the UI to make it easier for users to identify the API key."},"prefix":{"type":"string","nullable":true,"description":"The API Key prefix. Stored as plain text."},"userId":{"type":"string","description":"The owner of the user id"},"refillInterval":{"type":"number","nullable":true,"description":"The interval in milliseconds between refills of the `remaining` count. Example: 3600000 // refill every hour (3600000ms = 1h)"},"refillAmount":{"type":"number","nullable":true,"description":"The amount to refill"},"lastRefillAt":{"type":"string","format":"date-time","nullable":true,"description":"The last refill date"},"enabled":{"type":"boolean","description":"Sets if key is enabled or disabled","default":true},"rateLimitEnabled":{"type":"boolean","description":"Whether the key has rate limiting enabled"},"rateLimitTimeWindow":{"type":"number","nullable":true,"description":"The duration in milliseconds"},"rateLimitMax":{"type":"number","nullable":true,"description":"Maximum amount of requests allowed within a window"},"requestCount":{"type":"number","description":"The number of requests made within the rate limit time window"},"remaining":{"type":"number","nullable":true,"description":"Remaining requests (every time api key is used this should updated and should be updated on refill as well)"},"lastRequest":{"type":"string","format":"date-time","nullable":true,"description":"When last request occurred"},"expiresAt":{"type":"string","format":"date-time","nullable":true,"description":"Expiry date of a key"},"createdAt":{"type":"string","format":"date-time","description":"created at"},"updatedAt":{"type":"string","format":"date-time","description":"updated at"},"metadata":{"type":"object","nullable":true,"additionalProperties":true,"description":"Extra metadata about the apiKey"},"permissions":{"type":"string","nullable":true,"description":"Permissions for the api key (stored as JSON string)"}},"required":["id","userId","enabled","rateLimitEnabled","requestCount","createdAt","updatedAt"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/api-key/delete":{"post":{"tags":["Authentication"],"description":"Delete an existing API key","security":[{"bearerAuth":[]}],"parameters":[],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"keyId":{"type":"string","description":"The id of the API key to delete"}},"required":["keyId"]}}}},"responses":{"200":{"description":"API key deleted successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean","description":"Indicates if the API key was successfully deleted"}},"required":["success"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}},"/api/auth/api-key/list":{"get":{"tags":["Authentication"],"description":"List all API keys for the authenticated user or for a specific organization","security":[{"bearerAuth":[]}],"parameters":[],"responses":{"200":{"description":"API keys retrieved successfully","content":{"application/json":{"schema":{"type":"object","properties":{"apiKeys":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","description":"ID"},"name":{"type":"string","nullable":true,"description":"The name of the key"},"start":{"type":"string","nullable":true,"description":"Shows the first few characters of the API key, including the prefix. This allows you to show those few characters in the UI to make it easier for users to identify the API key."},"prefix":{"type":"string","nullable":true,"description":"The API Key prefix. Stored as plain text."},"userId":{"type":"string","description":"The owner of the user id"},"refillInterval":{"type":"number","nullable":true,"description":"The interval in milliseconds between refills of the `remaining` count. Example: 3600000 // refill every hour (3600000ms = 1h)"},"refillAmount":{"type":"number","nullable":true,"description":"The amount to refill"},"lastRefillAt":{"type":"string","format":"date-time","nullable":true,"description":"The last refill date"},"enabled":{"type":"boolean","description":"Sets if key is enabled or disabled","default":true},"rateLimitEnabled":{"type":"boolean","description":"Whether the key has rate limiting enabled"},"rateLimitTimeWindow":{"type":"number","nullable":true,"description":"The duration in milliseconds"},"rateLimitMax":{"type":"number","nullable":true,"description":"Maximum amount of requests allowed within a window"},"requestCount":{"type":"number","description":"The number of requests made within the rate limit time window"},"remaining":{"type":"number","nullable":true,"description":"Remaining requests (every time api key is used this should updated and should be updated on refill as well)"},"lastRequest":{"type":"string","format":"date-time","nullable":true,"description":"When last request occurred"},"expiresAt":{"type":"string","format":"date-time","nullable":true,"description":"Expiry date of a key"},"createdAt":{"type":"string","format":"date-time","description":"created at"},"updatedAt":{"type":"string","format":"date-time","description":"updated at"},"metadata":{"type":"object","nullable":true,"additionalProperties":true,"description":"Extra metadata about the apiKey"},"permissions":{"type":"string","nullable":true,"description":"Permissions for the api key (stored as JSON string)"}},"required":["id","userId","enabled","rateLimitEnabled","requestCount","createdAt","updatedAt"]}},"total":{"type":"number","description":"Total number of API keys"},"limit":{"type":"number","nullable":true,"description":"The limit used for pagination"},"offset":{"type":"number","nullable":true,"description":"The offset used for pagination"}},"required":["apiKeys","total"]}}}},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Bad Request. Usually due to missing parameters, or invalid parameters."},"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}},"description":"Unauthorized. Due to missing or invalid authentication."},"403":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Forbidden. You do not have permission to access this resource or to perform this action."},"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Not Found. The requested resource was not found."},"429":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Too Many Requests. You have exceeded the rate limit. Try again later."},"500":{"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}},"description":"Internal Server Error. This is a problem with the server that you cannot fix."}},"servers":[{"url":"https://app.owlic.fr","description":"Owlic app (auth endpoints)"}]}}},"webhooks":{}}