{"openapi":"3.0.3","info":{"title":"Recodex Clinique IA API","version":"1.0.0","description":"Public developer surface for Recodex Clinique IA, the clinical platform for psychologists. Stable routes live under /api/v1. Breaking changes require a new major path such as /api/v2. The unversioned /api/health alias is deprecated (Deprecation: @1791590400) and sends Sunset: Fri, 01 Oct 2027 00:00:00 GMT. Errors use RFC 9457 application/problem+json with a machine-readable code and a resolution hint. OAuth token errors keep the RFC 6749 error field and add the same hints. Rate limits: 120 requests per 60 seconds. Responses send RateLimit-Policy and RateLimit. A 429 also sends Retry-After. This document does not expose patient records."},"servers":[{"url":"https://recodexcliqueia.com","description":"Recodex Clinique IA production API"}],"tags":[{"name":"discovery","description":"Machine-readable discovery documents"},{"name":"oauth","description":"OAuth 2.0 authorization server"},{"name":"mcp","description":"Remote MCP server for an authorized psychologist"}],"paths":{"/.well-known/oauth-authorization-server":{"get":{"tags":["discovery","oauth"],"operationId":"getOAuthAuthorizationServerMetadata","summary":"OAuth 2.0 authorization server metadata (RFC 8414)","description":"Publish the authorization server metadata. The issuer equals the origin that served this document.","responses":{"200":{"description":"Authorization server metadata.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AuthorizationServerMetadata"}}}},"405":{"description":"Use GET.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/.well-known/oauth-protected-resource":{"get":{"tags":["discovery","oauth"],"operationId":"getOAuthProtectedResourceMetadata","summary":"OAuth 2.0 protected resource metadata (RFC 9728)","description":"Identify the MCP resource and the authorization server a client must use.","responses":{"200":{"description":"Protected resource metadata for the MCP resource.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProtectedResourceMetadata"}}}},"405":{"description":"Use GET.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/.well-known/api-catalog":{"get":{"tags":["discovery"],"operationId":"getApiCatalog","summary":"API catalog (RFC 9727)","description":"Link set pointing agents to the OpenAPI description and the developer docs.","responses":{"200":{"description":"RFC 9727 linkset.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/linkset+json":{"schema":{"$ref":"#/components/schemas/ApiCatalog"}}}},"405":{"description":"Use GET.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/v1/health":{"get":{"tags":["discovery"],"operationId":"getHealthV1","summary":"Versioned public health probe","description":"Stable health probe. Returns no clinical data and no infrastructure secrets. This is the current major version.","parameters":[{"name":"API-Version","in":"header","required":false,"schema":{"type":"string","enum":["1"]},"description":"Optional major version hint. The path /api/v1 is authoritative."}],"responses":{"200":{"description":"Dependencies responded. status is ok or degraded.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthReport"}}}},"401":{"description":"The deployment requires x-health-token.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthFailure"}}}},"405":{"description":"Use GET.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Quota exceeded. Honor Retry-After.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Dependencies are down or the deployment is misconfigured.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthReport"}}}}}}},"/api/health":{"get":{"tags":["discovery"],"operationId":"getHealth","summary":"Deprecated public health probe","description":"Compatibility alias of /api/v1/health. Deprecated on @1791590400. Sunset Fri, 01 Oct 2027 00:00:00 GMT. Same JSON body, plus Deprecation and Sunset headers.","deprecated":true,"responses":{"200":{"description":"Probe completed. Prefer /api/v1/health.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}},"Deprecation":{"description":"RFC 9745 deprecation date.","schema":{"type":"string","example":"@1791590400"}},"Sunset":{"description":"RFC 8594 sunset date.","schema":{"type":"string","example":"Fri, 01 Oct 2027 00:00:00 GMT"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthReport"}}}},"401":{"description":"The deployment requires x-health-token.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthFailure"}}}},"405":{"description":"Use GET.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Quota exceeded. Honor Retry-After.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Dependencies are down or the deployment is misconfigured.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HealthReport"}}}}}}},"/api/oauth/authorize":{"get":{"tags":["oauth"],"operationId":"authorizeOAuth","summary":"OAuth 2.0 authorization code endpoint with PKCE","description":"Start the authorization code flow for an authenticated psychologist. Redirects to login or consent when needed.","parameters":[{"name":"response_type","in":"query","required":true,"schema":{"type":"string","enum":["code"]},"description":"Must be code."},{"name":"client_id","in":"query","required":true,"schema":{"type":"string"},"description":"Registered public client."},{"name":"redirect_uri","in":"query","required":true,"schema":{"type":"string"},"description":"Registered redirect URI."},{"name":"code_challenge","in":"query","required":true,"schema":{"type":"string"},"description":"PKCE S256 challenge."},{"name":"code_challenge_method","in":"query","required":true,"schema":{"type":"string","enum":["S256"]},"description":"Must be S256."},{"name":"scope","in":"query","schema":{"type":"string","example":"recodex.clinical.read"},"description":"Requested scope."},{"name":"state","in":"query","schema":{"type":"string"},"description":"Opaque client state."}],"responses":{"302":{"description":"Redirects to the psychologist login, consent screen, or the client redirect URI.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}},"Location":{"description":"Absolute redirect target.","schema":{"type":"string","format":"uri"}}},"content":{"text/html":{"schema":{"type":"string","description":"Optional redirect document."}}}},"400":{"description":"Invalid authorization request.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"405":{"description":"Use GET.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Quota exceeded. Honor Retry-After.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/oauth/token":{"post":{"tags":["oauth"],"operationId":"exchangeOAuthToken","summary":"Exchange an authorization code or refresh token","description":"Token endpoint. Public clients authenticate with method none and send code_verifier for the authorization code grant.","requestBody":{"required":true,"content":{"application/x-www-form-urlencoded":{"schema":{"$ref":"#/components/schemas/TokenRequest"}},"application/json":{"schema":{"$ref":"#/components/schemas/TokenRequest"}}}},"responses":{"200":{"description":"Access token for scope recodex.clinical.read.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/TokenResponse"}}}},"400":{"description":"invalid_request, invalid_grant, or unsupported_grant_type.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"405":{"description":"Use POST.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Quota exceeded. Honor Retry-After.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/oauth/register":{"post":{"tags":["oauth"],"operationId":"registerOAuthClient","summary":"Dynamic client registration","description":"Register a public OAuth client. Returns client_id. No client secret is issued.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientRegistrationRequest"}}}},"responses":{"200":{"description":"Registered public client.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClientRegistrationResponse"}}}},"400":{"description":"Invalid registration request.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OAuthError"}}}},"405":{"description":"Use POST.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Quota exceeded. Honor Retry-After.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/mcp":{"post":{"tags":["mcp"],"operationId":"callMcp","summary":"Remote MCP endpoint for an authorized psychologist","description":"Streamable HTTP MCP. Requires a bearer token with scope recodex.clinical.read. resources/read returns the patient selector HTML view.","security":[{"oauth2":["recodex.clinical.read"]}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpRequest"}}}},"responses":{"200":{"description":"MCP JSON-RPC response.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/McpResponse"}}}},"401":{"description":"Missing or invalid bearer token.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"405":{"description":"Use POST, GET, or DELETE as required by Streamable HTTP.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Quota exceeded. Honor Retry-After.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"The MCP handler failed. Retry once, then read /docs.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/api/contact":{"post":{"tags":["discovery"],"operationId":"submitContact","summary":"Public contact form","description":"Accept a public contact message. Does not create a patient record.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactRequest"}}}},"responses":{"200":{"description":"Message accepted.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContactAccepted"}}}},"400":{"description":"Invalid payload. The error field remains invalid_payload.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"405":{"description":"Use POST.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"429":{"description":"Quota exceeded. Honor Retry-After.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"500":{"description":"The request body could not be read.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"502":{"description":"The mail provider rejected the message.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}},"503":{"description":"Email is not configured. Use the address on /fr/contact.","headers":{"RateLimit-Policy":{"description":"IETF RateLimit-Policy. Public quota is 120 requests per 60 seconds.","schema":{"type":"string"}},"RateLimit":{"description":"IETF RateLimit structured field: remaining requests and seconds until reset.","schema":{"type":"string"}},"Retry-After":{"description":"Present on 429. Seconds to wait before retrying.","schema":{"type":"integer"}}},"content":{"application/problem+json":{"schema":{"$ref":"#/components/schemas/ProblemDetails"}}}}}}},"/llms.txt":{"get":{"tags":["discovery"],"operationId":"getLlmsTxt","summary":"Agent instructions, including when to use Recodex","description":"When to use Recodex Clinique IA, and links to the docs, OpenAPI, OAuth metadata and MCP endpoint.","responses":{"200":{"description":"llms.txt","content":{"text/plain":{"schema":{"type":"string","description":"Agent instructions in plain text."}}}}}}},"/docs":{"get":{"tags":["discovery"],"operationId":"getDeveloperDocs","summary":"Developer documentation for Recodex Clinique IA","description":"Human documentation for the API, OAuth, versioning, errors and the MCP view.","responses":{"200":{"description":"HTML, or Markdown when Accept is text/markdown.","content":{"text/html":{"schema":{"type":"string"}},"text/markdown":{"schema":{"type":"string"}}}}}}}},"components":{"securitySchemes":{"oauth2":{"type":"oauth2","flows":{"authorizationCode":{"authorizationUrl":"https://recodexcliqueia.com/api/oauth/authorize","tokenUrl":"https://recodexcliqueia.com/api/oauth/token","scopes":{"recodex.clinical.read":"Read clinical context for the authenticated psychologist"}}}}},"schemas":{"ProblemDetails":{"type":"object","additionalProperties":true,"required":["type","title","status","detail","instance","code","resolution"],"properties":{"type":{"type":"string","format":"uri"},"title":{"type":"string"},"status":{"type":"integer"},"detail":{"type":"string"},"instance":{"type":"string","format":"uri"},"code":{"type":"string"},"resolution":{"type":"string"},"documentation_url":{"type":"string","format":"uri"},"error":{"type":"string","description":"Legacy code kept for existing clients."}}},"OAuthError":{"type":"object","required":["error","error_description","code","message","resolution"],"properties":{"error":{"type":"string"},"error_description":{"type":"string"},"code":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"}}},"HealthFailure":{"type":"object","required":["status","code","message","resolution"],"properties":{"status":{"type":"string","enum":["unauthorized"]},"code":{"type":"string"},"error":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"}}},"HealthReport":{"type":"object","required":["status","checks"],"properties":{"status":{"type":"string","enum":["ok","degraded","down","misconfigured","unauthorized"]},"code":{"type":"string"},"error":{"type":"string"},"message":{"type":"string"},"resolution":{"type":"string"},"checks":{"type":"object","required":["auth","database"],"properties":{"auth":{"type":"string","enum":["ok","slow","down"]},"database":{"type":"string","enum":["ok","slow","down"]}}},"timings":{"type":"object","properties":{"authMs":{"type":"integer"},"databaseMs":{"type":"integer"}}},"totalMs":{"type":"integer"},"at":{"type":"string","format":"date-time"}}},"AuthorizationServerMetadata":{"type":"object","required":["issuer","authorization_endpoint","token_endpoint","response_types_supported"],"properties":{"issuer":{"type":"string","format":"uri"},"authorization_endpoint":{"type":"string","format":"uri"},"token_endpoint":{"type":"string","format":"uri"},"registration_endpoint":{"type":"string","format":"uri"},"response_types_supported":{"type":"array","items":{"type":"string"}},"grant_types_supported":{"type":"array","items":{"type":"string"}},"code_challenge_methods_supported":{"type":"array","items":{"type":"string"}},"scopes_supported":{"type":"array","items":{"type":"string"}}}},"ProtectedResourceMetadata":{"type":"object","required":["resource","authorization_servers"],"properties":{"resource":{"type":"string","format":"uri"},"authorization_servers":{"type":"array","items":{"type":"string","format":"uri"}},"scopes_supported":{"type":"array","items":{"type":"string"}},"bearer_methods_supported":{"type":"array","items":{"type":"string"}}}},"ApiCatalog":{"type":"object","required":["linkset"],"properties":{"linkset":{"type":"array","items":{"type":"object","additionalProperties":true}}}},"TokenRequest":{"type":"object","required":["grant_type"],"properties":{"grant_type":{"type":"string","enum":["authorization_code","refresh_token"]},"code":{"type":"string"},"redirect_uri":{"type":"string"},"client_id":{"type":"string"},"code_verifier":{"type":"string"},"refresh_token":{"type":"string"}}},"TokenResponse":{"type":"object","required":["access_token","token_type","expires_in"],"properties":{"access_token":{"type":"string"},"token_type":{"type":"string","enum":["Bearer"]},"expires_in":{"type":"integer"},"refresh_token":{"type":"string"},"scope":{"type":"string"}}},"ClientRegistrationRequest":{"type":"object","required":["redirect_uris"],"properties":{"redirect_uris":{"type":"array","items":{"type":"string"}},"client_name":{"type":"string"}}},"ClientRegistrationResponse":{"type":"object","required":["client_id","redirect_uris","token_endpoint_auth_method"],"properties":{"client_id":{"type":"string"},"client_id_issued_at":{"type":"integer"},"redirect_uris":{"type":"array","items":{"type":"string"}},"token_endpoint_auth_method":{"type":"string","enum":["none"]},"grant_types":{"type":"array","items":{"type":"string"}},"response_types":{"type":"array","items":{"type":"string"}}}},"McpRequest":{"type":"object","required":["jsonrpc","method"],"properties":{"jsonrpc":{"type":"string","enum":["2.0"]},"id":{"type":"string"},"method":{"type":"string"},"params":{"type":"object","additionalProperties":true}}},"McpResponse":{"type":"object","properties":{"jsonrpc":{"type":"string"},"id":{"type":"string"},"result":{"type":"object","additionalProperties":true},"error":{"type":"object","additionalProperties":true}}},"ContactRequest":{"type":"object","required":["name","email","role","message"],"properties":{"name":{"type":"string"},"email":{"type":"string","format":"email"},"role":{"type":"string"},"message":{"type":"string"}}},"ContactAccepted":{"type":"object","required":["ok"],"properties":{"ok":{"type":"boolean"}}}}}}