{"openapi":"3.1.0","info":{"title":"Discence REST API","version":"1.0.0","x-audience":"Workspace administrators and integration partners","description":"REST API for the Discence learning platform. All workspace endpoints are rooted at `/api/v1` and return JSON.\n\n## Authentication\nThree credentials are supported.\n- **Session cookie** (`better-auth.session_token`): issued by the `/api/auth/*` endpoints. Interactive users sign in with email/password (`POST /api/auth/sign-in/email`), through an OAuth 2.0 authorization-code flow against a configured provider (`POST /api/auth/sign-in/social` with `provider`, currently `google`, then `GET /api/auth/callback/{provider}`), or through enterprise single sign-on (`POST /api/auth/sign-in/sso` — SAML 2.0 or OIDC, provider registered by a super administrator, IdP groups mapped to application roles). OAuth 2.0 tokens stay server-side; the API surface is the session cookie.\n- **Workspace API key**: send `x-api-key: dsk_…` or `Authorization: Bearer dsk_…`. Keys are created by workspace admins (`POST /api/v1/api-keys`), are bound to one workspace, and act with the creator's current workspace role. The plaintext is shown once at creation; only its SHA-256 hash is stored.\n- **Cron secret**: `Authorization: Bearer <CRON_SECRET>` guards `POST /api/v1/cron/health` (operations only).\n\nMembers of several workspaces select one per request with the `x-workspace-id` header; API-key callers always resolve to the key's workspace. Roles follow owner > admin > member > viewer > guest.\n\n## Errors\nFailures return `{\"error\": string}`; validation failures add `details: [{field, message}]` and status 400. Authentication failures are 401, authorization failures 403, missing resources 404.\n\n## Webhooks\nRegistrations subscribe an endpoint to workspace events. Each registration stores a secret reserved for signing outbound `X-Hub-Signature-256` (`sha256=<hex HMAC-SHA256>`) deliveries."},"servers":[{"url":"/","description":"Same origin as the deployed app"}],"tags":[{"name":"Authentication","description":"Better Auth sign-in surface; issues the session cookie. Includes the OAuth 2.0 and SAML 2.0/OIDC SSO flows."},{"name":"System","description":"Health, operations, feature flags, and queue probes."},{"name":"Agents","description":"Workspace AI agents."},{"name":"Threads","description":"Conversation threads and messages."},{"name":"Memory","description":"Per-agent key/value memory."},{"name":"Skills","description":"Reusable agent skill bodies."},{"name":"Tools","description":"Tool definitions an agent may call."},{"name":"Items","description":"Typed workspace records."},{"name":"Notes","description":"Per-user scratch notes."},{"name":"Settings","description":"Workspace key/value settings."},{"name":"Uploads","description":"File-transfer flow: declare, stream content, complete."},{"name":"Users","description":"Workspace members."},{"name":"Workspaces","description":"Tenant workspaces and membership."},{"name":"API Keys","description":"Workspace API-key management (admin)."},{"name":"Webhooks","description":"Outbound webhook registrations."},{"name":"Audit","description":"Workspace audit log."},{"name":"Billing","description":"Plans, entitlements, and billing event ingress."},{"name":"Contact","description":"Public contact form."}],"paths":{"/api/auth/sign-up/email":{"post":{"operationId":"signUpEmail","tags":["Authentication"],"x-auth":"none","summary":"Create an account with email and password","x-summary-fr":"Créer un compte avec courriel et mot de passe","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","email","password"],"properties":{"name":{"type":"string"},"email":{"type":"string","format":"email"},"password":{"type":"string","format":"password","minLength":8}}}}}},"responses":{"200":{"description":"User and session; session cookie set.","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/auth/sign-in/email":{"post":{"operationId":"signInEmail","tags":["Authentication"],"x-auth":"none","summary":"Sign in with email and password","x-summary-fr":"Ouvrir une session avec courriel et mot de passe","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string","format":"email"},"password":{"type":"string","format":"password"}}}}}},"responses":{"200":{"description":"Session established; `better-auth.session_token` cookie set (7-day expiry).","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/auth/sign-in/social":{"post":{"operationId":"signInSocial","tags":["Authentication"],"x-auth":"none","summary":"Start an OAuth 2.0 sign-in flow","x-summary-fr":"Démarrer une connexion OAuth 2.0","description":"Returns `{ url }`, the provider's OAuth 2.0 authorization URL (authorization-code flow; PKCE handled server-side by Better Auth). Providers are enabled per deployment via environment secrets; `google` is the configured provider. Redirect the user agent to `url`.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["provider"],"properties":{"provider":{"type":"string","enum":["google"]},"callbackURL":{"type":"string","format":"uri"}}}}}},"responses":{"200":{"description":"Authorization URL to redirect to.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/auth/callback/{provider}":{"get":{"operationId":"oauthCallback","tags":["Authentication"],"x-auth":"none","summary":"OAuth 2.0 provider redirect target","x-summary-fr":"URL de redirection du fournisseur OAuth 2.0","description":"The provider redirects here with `code` and `state`. On success the session cookie is set and the user agent is redirected into the app. Access and refresh tokens are held server-side and are not exposed through the API.","security":[],"parameters":[{"name":"provider","in":"path","required":true,"schema":{"type":"string","enum":["google"]}},{"name":"code","in":"query","required":true,"schema":{"type":"string"}},{"name":"state","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect into the app with the session cookie set."},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/auth/sign-in/sso":{"post":{"operationId":"signInSso","tags":["Authentication"],"x-auth":"none","summary":"Start a SAML 2.0 or OIDC single sign-on flow","x-summary-fr":"Démarrer une authentification unique SAML 2.0 ou OIDC","description":"Returns `{ url }`, the identity provider's authorization or SSO URL. Name the provider with `providerId`, or let the server resolve it from `domain`, `email`, or `organizationSlug`. Redirect the user agent to `url`. A super administrator registers providers; IdP group claims map to application roles on every sign-in (NON.FUNC4, NON.FUNC52).","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["callbackURL"],"properties":{"providerId":{"type":"string"},"domain":{"type":"string"},"email":{"type":"string","format":"email"},"organizationSlug":{"type":"string"},"callbackURL":{"type":"string","format":"uri"}}}}}},"responses":{"200":{"description":"IdP URL to redirect to.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"redirect":{"type":"boolean"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/auth/sso/callback/{providerId}":{"get":{"operationId":"ssoOidcCallback","tags":["Authentication"],"x-auth":"none","summary":"OIDC provider redirect target","x-summary-fr":"URL de redirection du fournisseur OIDC","description":"The OIDC provider redirects here after authentication. On success the session cookie is set and the user agent is redirected into the app.","security":[],"parameters":[{"name":"providerId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect into the app with the session cookie set."},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/auth/sso/saml2/callback/{providerId}":{"post":{"operationId":"samlAcs","tags":["Authentication"],"x-auth":"none","summary":"SAML 2.0 assertion consumer service","x-summary-fr":"Service consommateur d'assertions SAML 2.0","description":"The IdP posts the SAML response here (POST binding; GET redirect binding is also accepted). On success the session cookie is set and the user agent is redirected into the app.","security":[],"parameters":[{"name":"providerId","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"302":{"description":"Redirect into the app with the session cookie set."},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/auth/sso/saml2/sp/metadata":{"get":{"operationId":"samlSpMetadata","tags":["Authentication"],"x-auth":"none","summary":"SAML 2.0 service-provider metadata","x-summary-fr":"Métadonnées du fournisseur de service SAML 2.0","description":"Service-provider metadata for registering the app at the IdP. Returns SAML XML by default; `format=json` returns the same fields as JSON.","security":[],"parameters":[{"name":"providerId","in":"query","required":true,"schema":{"type":"string"}},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["xml","json"]}}],"responses":{"200":{"description":"Service-provider metadata (SAML XML or JSON)."},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/auth/get-session":{"get":{"operationId":"getSession","tags":["Authentication"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"Return the current session and user","x-summary-fr":"Retourner la session et l'utilisateur courants","responses":{"200":{"description":"Session and user objects, or null when signed out.","content":{"application/json":{"schema":{"type":["object","null"]}}}}}}},"/api/auth/sign-out":{"post":{"operationId":"signOut","tags":["Authentication"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"End the session","x-summary-fr":"Fermer la session","responses":{"200":{"description":"Session revoked; cookie cleared.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/v1/learn/progress":{"post":{"operationId":"recordLearnProgress","tags":["Learning"],"x-auth":"session","summary":"Record a learner activity event","x-summary-fr":"Enregistrer un événement d'activité d'apprenant","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["activityId","event","secondsSpent"],"properties":{"activityId":{"type":"string","minLength":1,"maxLength":64},"event":{"type":"string","enum":["open","save","complete"]},"resumeState":{"description":"Opaque per-activity resume payload (FUNC.11)."},"resumeRevision":{"type":"integer","minimum":0},"secondsSpent":{"type":"integer","minimum":0,"maximum":86400}}}}}},"responses":{"200":{"description":"Event recorded.","content":{"application/json":{"schema":{"type":"object","required":["status"],"properties":{"status":{"type":"string","enum":["in_progress","completed"]},"moduleNumber":{"type":"integer"},"modulePercent":{"type":"integer"}}}}}}}}},"/api/v1/health":{"get":{"operationId":"healthCheck","tags":["System"],"x-auth":"none","summary":"Service liveness probe","x-summary-fr":"Sonde de disponibilité du service","security":[],"responses":{"200":{"description":"Service is up.","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true},"service":{"type":"string"},"time":{"type":"string","format":"date-time"}}}}}}}}},"/api/v1/cron/health":{"get":{"operationId":"cronHealth","tags":["System"],"x-auth":"none","summary":"Cron pipeline liveness probe","x-summary-fr":"Sonde de disponibilité du pipeline cron","security":[],"responses":{"200":{"description":"Cron pipeline is up.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"service":{"type":"string"}}}}}}}},"post":{"operationId":"drainOutbox","tags":["System"],"x-auth":"cron","security":[{"cronSecret":[]}],"summary":"Drain a batch of pending outbox jobs","x-summary-fr":"Traiter un lot de tâches outbox en attente","description":"Operations endpoint invoked by the cron Worker. Requires `Authorization: Bearer <CRON_SECRET>` (a deployment secret, not a user credential).","responses":{"200":{"description":"Drained batch.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"drained":{"type":"integer"},"cron":{"type":["string","null"]}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/v1/openapi.json":{"get":{"operationId":"getOpenApiSpec","tags":["System"],"x-auth":"none","summary":"This OpenAPI 3.1 document","x-summary-fr":"Le présent document OpenAPI 3.1","security":[],"responses":{"200":{"description":"The OpenAPI document.","content":{"application/json":{"schema":{"type":"object"}}}}}}},"/api/v1/flags":{"get":{"operationId":"listFlags","tags":["System"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"List feature flags","x-summary-fr":"Lister les indicateurs de fonctionnalité","responses":{"200":{"description":"Flags from the FLAGS store.","content":{"application/json":{"schema":{"type":"object","properties":{"flags":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"value":{}}}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"operationId":"setFlag","tags":["System"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"Set a feature flag","x-summary-fr":"Définir un indicateur de fonctionnalité","description":"Writes require a non-production environment or a caller listed in `FLAGS_ADMIN_EMAILS` (403 otherwise). Flag names match `[a-zA-Z0-9._-]{1,64}`.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name","value"],"properties":{"name":{"type":"string","pattern":"^[a-zA-Z0-9._-]{1,64}$"},"value":{}}}}}},"responses":{"200":{"description":"Flag written.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"name":{"type":"string"},"value":{}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/api/v1/jobs/demo":{"post":{"operationId":"enqueueDemoJob","tags":["System"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"Enqueue a demo job on the outbox queue","x-summary-fr":"Mettre une tâche de démonstration en file","requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}}}}}},"responses":{"200":{"description":"Job enqueued.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"jobId":{"type":"string"},"message":{"type":"string"},"job":{"type":"object"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/v1/agents":{"get":{"operationId":"listAgents","tags":["Agents"],"x-auth":"user","summary":"List workspace agents","x-summary-fr":"Lister les agents de l'espace de travail","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Newest first, up to 100.","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Agent"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"operationId":"createAgent","tags":["Agents"],"x-auth":"user","summary":"Create an agent","x-summary-fr":"Créer un agent","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAgent"}}}},"responses":{"201":{"description":"Created agent.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Agent"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/agents/{id}":{"get":{"operationId":"getAgent","tags":["Agents"],"x-auth":"user","summary":"Get an agent","x-summary-fr":"Obtenir un agent","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"The agent.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Agent"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"deleteAgent","tags":["Agents"],"x-auth":"user","summary":"Delete an agent","x-summary-fr":"Supprimer un agent","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/audit-logs":{"get":{"operationId":"listAuditLogs","tags":["Audit"],"x-auth":"user","summary":"List workspace audit log entries","x-summary-fr":"Lister les entrées du journal d'audit","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Newest first.","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/AuditLog"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/audit-logs/{id}":{"get":{"operationId":"getAuditLog","tags":["Audit"],"x-auth":"user","summary":"Get an audit log entry","x-summary-fr":"Obtenir une entrée du journal d'audit","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"The entry.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/AuditLog"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/billing/checkout":{"post":{"operationId":"createCheckout","tags":["Billing"],"x-auth":"admin","summary":"Start a plan checkout","x-summary-fr":"Démarrer un paiement de forfait","description":"Template implementation records the plan change and returns `checkoutUrl: null`; a Stripe Checkout URL is returned once the payment provider is wired.","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["plan"],"properties":{"plan":{"type":"string","enum":["pro","team"]}}}}}},"responses":{"200":{"description":"Checkout result.","content":{"application/json":{"schema":{"type":"object","properties":{"billing":{"$ref":"#/components/schemas/Billing"},"checkoutUrl":{"type":["string","null"]},"note":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/billing/info":{"get":{"operationId":"getBillingInfo","tags":["Billing"],"x-auth":"user","summary":"Get the workspace billing record","x-summary-fr":"Obtenir le dossier de facturation","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Billing record.","content":{"application/json":{"schema":{"type":"object","properties":{"billing":{"$ref":"#/components/schemas/Billing"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/billing/portal":{"post":{"operationId":"createPortalSession","tags":["Billing"],"x-auth":"admin","summary":"Create a billing portal session","x-summary-fr":"Créer une session du portail de facturation","description":"Returns `url: null` until the Stripe customer portal is configured.","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Portal session.","content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":["string","null"]},"customerId":{"type":["string","null"]},"note":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/billing/usage":{"get":{"operationId":"getBillingUsage","tags":["Billing"],"x-auth":"user","summary":"Get usage and entitlements","x-summary-fr":"Obtenir l'utilisation et les droits","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Usage counters and entitlements.","content":{"application/json":{"schema":{"type":"object","properties":{"usage":{"type":"object","properties":{"aiTokens":{"type":"integer"},"members":{"type":"integer"}}},"entitlements":{"type":"object"},"periodEnd":{"type":["string","null"],"format":"date-time"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/billing/webhook":{"post":{"operationId":"receiveBillingWebhook","tags":["Billing"],"x-auth":"stripe","summary":"Receive a billing provider event","x-summary-fr":"Recevoir un événement du fournisseur de facturation","description":"Stripe-compatible ingress. Each accepted event is stored for asynchronous reconciliation and acknowledged immediately.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"type":{"type":"string"}},"additionalProperties":true}}}},"responses":{"200":{"description":"Event stored.","content":{"application/json":{"schema":{"type":"object","properties":{"received":{"type":"boolean","const":true},"id":{"type":"string"}}}}}}}}},"/api/v1/contact":{"post":{"operationId":"submitContact","tags":["Contact"],"x-auth":"none","summary":"Submit the public contact form","x-summary-fr":"Soumettre le formulaire de contact public","description":"Verifies the Cloudflare Turnstile token when `TURNSTILE_SECRET_KEY` is configured (required in production), then enqueues a confirmation email.","security":[],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["email","message"],"properties":{"email":{"type":"string","format":"email"},"message":{"type":"string"},"turnstileToken":{"type":"string"}}}}}},"responses":{"200":{"description":"Submission accepted.","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"message":{"type":"string"},"email":{"type":"string"},"enqueued":{"type":"boolean"},"jobId":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"}}}},"/api/v1/items":{"get":{"operationId":"listItems","tags":["Items"],"x-auth":"user","summary":"List workspace items","x-summary-fr":"Lister les éléments de l'espace de travail","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Newest first.","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Item"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"operationId":"createItem","tags":["Items"],"x-auth":"user","summary":"Create an item","x-summary-fr":"Créer un élément","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["type"],"properties":{"type":{"type":"string","minLength":1,"maxLength":80},"title":{"type":"string","maxLength":255},"data":{"type":"object","additionalProperties":true}}}}}},"responses":{"201":{"description":"Created item.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Item"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/items/{id}":{"get":{"operationId":"getItem","tags":["Items"],"x-auth":"user","summary":"Get an item","x-summary-fr":"Obtenir un élément","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"The item.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Item"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"deleteItem","tags":["Items"],"x-auth":"user","summary":"Delete an item","x-summary-fr":"Supprimer un élément","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/memory":{"get":{"operationId":"listMemory","tags":["Memory"],"x-auth":"user","summary":"List agent memory entries","x-summary-fr":"Lister les entrées de mémoire d'agent","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Newest first.","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Memory"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"operationId":"createMemory","tags":["Memory"],"x-auth":"user","summary":"Store a memory entry","x-summary-fr":"Enregistrer une entrée de mémoire","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["agentId","key","value"],"properties":{"agentId":{"type":"string","minLength":1},"key":{"type":"string","minLength":1,"maxLength":200},"value":{"type":"object","additionalProperties":true}}}}}},"responses":{"201":{"description":"Created entry.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Memory"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/memory/{id}":{"get":{"operationId":"getMemory","tags":["Memory"],"x-auth":"user","summary":"Get a memory entry","x-summary-fr":"Obtenir une entrée de mémoire","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"The entry.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Memory"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"deleteMemory","tags":["Memory"],"x-auth":"user","summary":"Delete a memory entry","x-summary-fr":"Supprimer une entrée de mémoire","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/notes":{"get":{"operationId":"listNotes","tags":["Notes"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"List the caller's notes","x-summary-fr":"Lister les notes de l'appelant","responses":{"200":{"description":"Notes owned by the signed-in user.","content":{"application/json":{"schema":{"type":"object","required":["notes"],"properties":{"notes":{"type":"array","items":{"$ref":"#/components/schemas/Note"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"operationId":"createNote","tags":["Notes"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"Create a note","x-summary-fr":"Créer une note","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["title","body"],"properties":{"title":{"type":"string"},"body":{"type":"string"}}}}}},"responses":{"201":{"description":"Created note.","content":{"application/json":{"schema":{"type":"object","required":["note"],"properties":{"note":{"$ref":"#/components/schemas/Note"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}},"delete":{"operationId":"deleteNote","tags":["Notes"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"Delete a note","x-summary-fr":"Supprimer une note","parameters":[{"name":"id","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/v1/settings":{"get":{"operationId":"listSettings","tags":["Settings"],"x-auth":"user","summary":"List workspace settings","x-summary-fr":"Lister les paramètres de l'espace de travail","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Newest first.","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Setting"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"operationId":"createSetting","tags":["Settings"],"x-auth":"user","summary":"Set a workspace setting","x-summary-fr":"Définir un paramètre d'espace de travail","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["key","value"],"properties":{"key":{"type":"string","minLength":1,"maxLength":120},"value":{}}}}}},"responses":{"201":{"description":"Created setting.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Setting"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/settings/{id}":{"get":{"operationId":"getSetting","tags":["Settings"],"x-auth":"user","summary":"Get a setting","x-summary-fr":"Obtenir un paramètre","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"The setting.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Setting"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"deleteSetting","tags":["Settings"],"x-auth":"user","summary":"Delete a setting","x-summary-fr":"Supprimer un paramètre","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/skills":{"get":{"operationId":"listSkills","tags":["Skills"],"x-auth":"user","summary":"List agent skills","x-summary-fr":"Lister les compétences d'agent","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Newest first.","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Skill"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"operationId":"createSkill","tags":["Skills"],"x-auth":"user","summary":"Create a skill","x-summary-fr":"Créer une compétence","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["agentId","name","body"],"properties":{"agentId":{"type":"string","minLength":1},"name":{"type":"string","minLength":1,"maxLength":120},"body":{"type":"string","minLength":1},"description":{"type":"string","maxLength":2000}}}}}},"responses":{"201":{"description":"Created skill.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Skill"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/skills/{id}":{"get":{"operationId":"getSkill","tags":["Skills"],"x-auth":"user","summary":"Get a skill","x-summary-fr":"Obtenir une compétence","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"The skill.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Skill"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"deleteSkill","tags":["Skills"],"x-auth":"user","summary":"Delete a skill","x-summary-fr":"Supprimer une compétence","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/threads":{"get":{"operationId":"listThreads","tags":["Threads"],"x-auth":"user","summary":"List workspace threads","x-summary-fr":"Lister les fils de discussion","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Newest first.","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Thread"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"operationId":"createThread","tags":["Threads"],"x-auth":"user","summary":"Open a thread","x-summary-fr":"Ouvrir un fil de discussion","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["agentId"],"properties":{"agentId":{"type":"string","minLength":1},"title":{"type":"string","maxLength":200}}}}}},"responses":{"201":{"description":"Created thread.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Thread"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/threads/{id}":{"get":{"operationId":"getThread","tags":["Threads"],"x-auth":"user","summary":"Get a thread","x-summary-fr":"Obtenir un fil de discussion","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"The thread.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Thread"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"deleteThread","tags":["Threads"],"x-auth":"user","summary":"Delete a thread","x-summary-fr":"Supprimer un fil de discussion","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/threads/{id}/messages":{"get":{"operationId":"listMessages","tags":["Threads"],"x-auth":"user","summary":"List a thread's messages","x-summary-fr":"Lister les messages d'un fil","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Oldest first.","content":{"application/json":{"schema":{"type":"object","required":["messages"],"properties":{"messages":{"type":"array","items":{"$ref":"#/components/schemas/Message"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"operationId":"createMessage","tags":["Threads"],"x-auth":"user","summary":"Append a message","x-summary-fr":"Ajouter un message","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["content"],"properties":{"role":{"type":"string","enum":["user","assistant","system","tool"],"default":"user"},"content":{"type":"string","minLength":1}}}}}},"responses":{"201":{"description":"Created message; the thread's `messageCount` and `lastMessageAt` are updated.","content":{"application/json":{"schema":{"type":"object","required":["message"],"properties":{"message":{"$ref":"#/components/schemas/Message"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/tools":{"get":{"operationId":"listTools","tags":["Tools"],"x-auth":"user","summary":"List workspace tools","x-summary-fr":"Lister les outils de l'espace de travail","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Newest first.","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Tool"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"operationId":"createTool","tags":["Tools"],"x-auth":"user","summary":"Register a tool","x-summary-fr":"Enregistrer un outil","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":120},"description":{"type":"string","maxLength":2000},"kind":{"type":"string","enum":["builtin","integration"],"default":"builtin"}}}}}},"responses":{"201":{"description":"Created tool.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Tool"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/tools/{id}":{"get":{"operationId":"getTool","tags":["Tools"],"x-auth":"user","summary":"Get a tool","x-summary-fr":"Obtenir un outil","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"The tool.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Tool"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"deleteTool","tags":["Tools"],"x-auth":"user","summary":"Delete a tool","x-summary-fr":"Supprimer un outil","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/uploads":{"get":{"operationId":"listUploads","tags":["Uploads"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"List the caller's uploads","x-summary-fr":"Lister les téléversements de l'appelant","responses":{"200":{"description":"Upload records owned by the signed-in user.","content":{"application/json":{"schema":{"type":"object","required":["uploads"],"properties":{"uploads":{"type":"array","items":{"$ref":"#/components/schemas/Upload"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"operationId":"createUpload","tags":["Uploads"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"Declare a file upload","x-summary-fr":"Déclarer un téléversement de fichier","description":"Step 1 of the file-transfer flow. Validates the content type and size (max 50 MB), creates a `pending` record, and returns `putUrl` for the content stream. Allowed types: PNG, JPEG, WebP, GIF, PDF, plain text, CSV, JSON.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["filename","contentType","sizeBytes"],"properties":{"filename":{"type":"string"},"contentType":{"type":"string"},"sizeBytes":{"type":"integer","minimum":1,"maximum":52428800}}}}}},"responses":{"200":{"description":"Pending upload and its `putUrl`.","content":{"application/json":{"schema":{"type":"object","properties":{"uploadId":{"type":"string"},"key":{"type":"string"},"putUrl":{"type":"string"},"upload":{"$ref":"#/components/schemas/Upload"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/v1/uploads/{id}/content":{"put":{"operationId":"putUploadContent","tags":["Uploads"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"Stream file bytes","x-summary-fr":"Transférer le contenu du fichier","description":"Step 2: `PUT` the raw bytes to the `putUrl` from step 1. Only the upload owner may write; the body must not exceed the declared `sizeBytes`.","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"requestBody":{"required":true,"content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"responses":{"200":{"description":"Bytes stored.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"bytes":{"type":"integer"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"get":{"operationId":"getUploadContent","tags":["Uploads"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"Download file bytes","x-summary-fr":"Télécharger le contenu du fichier","description":"Streams the stored object back with its original `Content-Type`. Owner only.","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"The file bytes.","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/uploads/{id}/complete":{"post":{"operationId":"completeUpload","tags":["Uploads"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"Mark an upload ready","x-summary-fr":"Marquer un téléversement comme prêt","description":"Step 3: verifies the object exists in storage and flips the record to `ready` with the stored byte size.","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Upload marked ready.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"type":"boolean"},"upload":{"$ref":"#/components/schemas/Upload"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/users":{"get":{"operationId":"listUsers","tags":["Users"],"x-auth":"user","summary":"List workspace members","x-summary-fr":"Lister les membres de l'espace de travail","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Members of the resolved workspace.","content":{"application/json":{"schema":{"type":"object","required":["users"],"properties":{"users":{"type":"array","items":{"$ref":"#/components/schemas/Member"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/webhooks":{"get":{"operationId":"listWebhooks","tags":["Webhooks"],"x-auth":"user","summary":"List webhook registrations","x-summary-fr":"Lister les inscriptions de webhooks","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Newest first.","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"operationId":"createWebhook","tags":["Webhooks"],"x-auth":"user","summary":"Register a webhook","x-summary-fr":"Inscrire un webhook","description":"`secret` (min 8 chars) is reserved as the HMAC key for outbound `X-Hub-Signature-256` signatures; only its hash is stored. `events` is a non-empty list of event names to subscribe to.","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["agentId","url","secret","events"],"properties":{"agentId":{"type":"string","minLength":1},"url":{"type":"string","format":"uri"},"secret":{"type":"string","minLength":8},"events":{"type":"array","minItems":1,"items":{"type":"string"}}}}}}},"responses":{"201":{"description":"Created registration.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Webhook"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/webhooks/{id}":{"get":{"operationId":"getWebhook","tags":["Webhooks"],"x-auth":"user","summary":"Get a webhook registration","x-summary-fr":"Obtenir une inscription de webhook","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"The registration.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/Webhook"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"delete":{"operationId":"deleteWebhook","tags":["Webhooks"],"x-auth":"user","summary":"Delete a webhook registration","x-summary-fr":"Supprimer une inscription de webhook","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Deleted.","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/workspace/current":{"get":{"operationId":"getCurrentWorkspace","tags":["Workspaces"],"x-auth":"user","summary":"Resolve the active workspace","x-summary-fr":"Résoudre l'espace de travail actif","description":"Returns the workspace the request resolved to (the `x-workspace-id` header when present, otherwise the caller's first active membership) plus the caller's role in it.","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Resolved tenant context.","content":{"application/json":{"schema":{"type":"object","required":["workspaceId","role"],"properties":{"workspaceId":{"type":"string"},"role":{"type":"string"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/workspaces":{"get":{"operationId":"listWorkspaces","tags":["Workspaces"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"List the caller's workspaces","x-summary-fr":"Lister les espaces de travail de l'appelant","responses":{"200":{"description":"Every workspace the user belongs to, with role and status.","content":{"application/json":{"schema":{"type":"object","required":["workspaces"],"properties":{"workspaces":{"type":"array","items":{"$ref":"#/components/schemas/WorkspaceMembership"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}},"post":{"operationId":"createWorkspace","tags":["Workspaces"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"Create a workspace","x-summary-fr":"Créer un espace de travail","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":120}}}}}},"responses":{"201":{"description":"Created workspace; the creator becomes `owner`.","content":{"application/json":{"schema":{"type":"object","required":["workspace"],"properties":{"workspace":{"$ref":"#/components/schemas/Workspace"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/api/v1/workspaces/{id}":{"get":{"operationId":"getWorkspace","tags":["Workspaces"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"Get a workspace the caller belongs to","x-summary-fr":"Obtenir un espace de travail du membre","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Workspace with the caller's role.","content":{"application/json":{"schema":{"type":"object","required":["workspace"],"properties":{"workspace":{"$ref":"#/components/schemas/WorkspaceMembership"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/workspaces/{id}/members":{"get":{"operationId":"listWorkspaceMembers","tags":["Workspaces"],"x-auth":"session","security":[{"sessionCookie":[]}],"summary":"List a workspace's members","x-summary-fr":"Lister les membres d'un espace de travail","parameters":[{"$ref":"#/components/parameters/ResourceId"}],"responses":{"200":{"description":"Members; requires membership.","content":{"application/json":{"schema":{"type":"object","required":["members"],"properties":{"members":{"type":"array","items":{"$ref":"#/components/schemas/Member"}}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/api-keys":{"get":{"operationId":"listApiKeys","tags":["API Keys"],"x-auth":"admin","summary":"List workspace API keys","x-summary-fr":"Lister les clés API de l'espace de travail","description":"Returns key metadata only — prefixes, never hashes or plaintext.","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Newest first.","content":{"application/json":{"schema":{"type":"object","required":["items"],"properties":{"items":{"type":"array","items":{"$ref":"#/components/schemas/ApiKey"}}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}},"post":{"operationId":"createApiKey","tags":["API Keys"],"x-auth":"admin","summary":"Create an API key","x-summary-fr":"Créer une clé API","description":"The plaintext `key` (`dsk_…`) is returned only in this response. Store it as a secret; only its SHA-256 hash is persisted. The key is bound to this workspace and acts with the creator's current role.","parameters":[{"$ref":"#/components/parameters/WorkspaceId"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":120}}}}}},"responses":{"201":{"description":"Created key including the one-time plaintext.","content":{"application/json":{"schema":{"type":"object","required":["item"],"properties":{"item":{"$ref":"#/components/schemas/CreatedApiKey"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/api/v1/api-keys/{id}":{"delete":{"operationId":"revokeApiKey","tags":["API Keys"],"x-auth":"admin","summary":"Revoke an API key","x-summary-fr":"Révoquer une clé API","description":"Sets `revokedAt`; the key stops authenticating immediately.","parameters":[{"$ref":"#/components/parameters/ResourceId"},{"$ref":"#/components/parameters/WorkspaceId"}],"responses":{"200":{"description":"Revoked.","content":{"application/json":{"schema":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean","const":true}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}}},"security":[{"sessionCookie":[]},{"apiKey":[]}],"components":{"securitySchemes":{"sessionCookie":{"type":"apiKey","in":"cookie","name":"better-auth.session_token","description":"Issued by `/api/auth/*` after email/password or OAuth 2.0 sign-in. 7-day expiry."},"apiKey":{"type":"apiKey","in":"header","name":"x-api-key","description":"Workspace API key (`dsk_…`). `Authorization: Bearer dsk_…` is accepted equivalently. Create and revoke via `/api/v1/api-keys` (admin)."},"cronSecret":{"type":"http","scheme":"bearer","description":"Deployment `CRON_SECRET` for the operations endpoint `POST /api/v1/cron/health`. Not a user credential."}},"parameters":{"ResourceId":{"name":"id","in":"path","required":true,"schema":{"type":"string"},"description":"Resource identifier (prefix indicates the type, e.g. `agt_`, `thr_`, `key_`)."},"WorkspaceId":{"name":"x-workspace-id","in":"header","required":false,"schema":{"type":"string"},"description":"Workspace to operate in when the caller belongs to several. Defaults to the caller's first active membership. Ignored for API-key credentials, which are bound to their own workspace."}},"responses":{"BadRequest":{"description":"Malformed request or validation failure. Validation failures return `{\"error\":\"Validation failed\",\"details\":[{\"field\",\"message\"}]}`."},"Unauthorized":{"description":"Missing, invalid, expired, or revoked credentials."},"Forbidden":{"description":"Authenticated but insufficient role (or no active membership)."},"NotFound":{"description":"Resource does not exist in the resolved workspace."}},"schemas":{"Agent":{"type":"object","properties":{"id":{"type":"string","example":"agt_ck..."},"workspaceId":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"model":{"type":"string"},"systemPrompt":{"type":"string"},"isDefaultAiChat":{"type":"boolean"},"toolAllowlistJson":{"type":"string","description":"JSON array of enabled tool ids"},"publicKey":{"type":["string","null"]},"publicEnabled":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"updateCounter":{"type":"integer"}}},"CreateAgent":{"type":"object","required":["name"],"properties":{"name":{"type":"string","minLength":1,"maxLength":120},"model":{"type":"string","minLength":1,"maxLength":120,"default":"gpt-4o-mini"},"description":{"type":"string","maxLength":2000},"systemPrompt":{"type":"string"}}},"AuditLog":{"type":"object","properties":{"id":{"type":"string"},"workspaceId":{"type":"string"},"actorUserId":{"type":["string","null"]},"action":{"type":"string"},"targetType":{"type":["string","null"]},"targetId":{"type":["string","null"]},"metaJson":{"type":"string","description":"JSON object of event metadata"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"updateCounter":{"type":"integer"}}},"Billing":{"type":"object","properties":{"workspaceId":{"type":"string"},"plan":{"type":"string","enum":["free","pro","team"]},"status":{"type":"string"},"customerId":{"type":["string","null"]},"subscriptionId":{"type":["string","null"]},"currentPeriodEnd":{"type":["string","null"],"format":"date-time"},"cancelAtPeriodEnd":{"type":"boolean"},"entitlementsJson":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"updateCounter":{"type":"integer"}}},"Item":{"type":"object","properties":{"id":{"type":"string"},"workspaceId":{"type":"string"},"type":{"type":"string"},"title":{"type":"string"},"dataJson":{"type":"string","description":"JSON payload"},"createdByUserId":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"updateCounter":{"type":"integer"}}},"Member":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"role":{"type":"string"},"status":{"type":"string","enum":["active","pending"]},"email":{"type":["string","null"]},"joinedAt":{"type":["string","null"],"format":"date-time"}}},"Memory":{"type":"object","properties":{"id":{"type":"string"},"workspaceId":{"type":"string"},"agentId":{"type":"string"},"key":{"type":"string"},"valueJson":{"type":"string"},"embeddingJson":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"updateCounter":{"type":"integer"}}},"Message":{"type":"object","properties":{"id":{"type":"string"},"threadId":{"type":"string"},"workspaceId":{"type":"string"},"agentId":{"type":"string"},"role":{"type":"string","enum":["user","assistant","tool","system"]},"content":{"type":"string"},"toolName":{"type":["string","null"]},"toolCallId":{"type":["string","null"]},"usageInputTokens":{"type":["integer","null"]},"usageOutputTokens":{"type":["integer","null"]},"metadataJson":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"updateCounter":{"type":"integer"}}},"Note":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"title":{"type":"string"},"body":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"updateCounter":{"type":"integer"}}},"Setting":{"type":"object","properties":{"id":{"type":"string"},"workspaceId":{"type":"string"},"key":{"type":"string"},"valueJson":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"updateCounter":{"type":"integer"}}},"Skill":{"type":"object","properties":{"id":{"type":"string"},"workspaceId":{"type":"string"},"agentId":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"body":{"type":"string"},"enabled":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"updateCounter":{"type":"integer"}}},"Thread":{"type":"object","properties":{"id":{"type":"string"},"workspaceId":{"type":"string"},"agentId":{"type":"string"},"actor":{"type":"string","enum":["admin","member","visitor"]},"actorId":{"type":"string"},"visibility":{"type":"string","enum":["internal","public"]},"title":{"type":"string"},"status":{"type":"string","enum":["open","archived"]},"messageCount":{"type":"integer"},"lastMessageAt":{"type":["string","null"],"format":"date-time"},"metadataJson":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"updateCounter":{"type":"integer"}}},"Tool":{"type":"object","properties":{"id":{"type":"string"},"workspaceId":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"inputSchemaJson":{"type":"string"},"kind":{"type":"string","enum":["builtin","integration"]},"integrationId":{"type":["string","null"]},"enabled":{"type":"boolean"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"updateCounter":{"type":"integer"}}},"Upload":{"type":"object","properties":{"id":{"type":"string"},"userId":{"type":"string"},"workspaceId":{"type":["string","null"]},"key":{"type":"string"},"filename":{"type":"string"},"contentType":{"type":"string"},"sizeBytes":{"type":"integer"},"status":{"type":"string","enum":["pending","ready","failed"]},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"updateCounter":{"type":"integer"}}},"Webhook":{"type":"object","properties":{"id":{"type":"string"},"workspaceId":{"type":"string"},"agentId":{"type":"string"},"url":{"type":"string","format":"uri"},"secretHash":{"type":"string","description":"SHA-256 of the signing secret; the secret itself is never returned"},"eventsJson":{"type":"string","description":"JSON array of subscribed event names"},"enabled":{"type":"boolean"},"failureCount":{"type":"integer"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"updateCounter":{"type":"integer"}}},"Workspace":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"}}},"WorkspaceMembership":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"slug":{"type":"string"},"role":{"type":"string"},"status":{"type":"string","enum":["active","pending"]}}},"ApiKey":{"type":"object","properties":{"id":{"type":"string"},"workspaceId":{"type":"string"},"name":{"type":"string"},"prefix":{"type":"string","example":"dsk_a1b2c3d4"},"createdByUserId":{"type":["string","null"]},"lastUsedAt":{"type":["string","null"],"format":"date-time"},"revokedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}}},"CreatedApiKey":{"allOf":[{"$ref":"#/components/schemas/ApiKey"},{"type":"object","required":["key"],"properties":{"key":{"type":"string","description":"Full plaintext key, returned only at creation."}}}]},"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"},"details":{"type":"array","items":{"type":"object","properties":{"field":{"type":"string"},"message":{"type":"string"}}}}}}}}}