{"openapi":"3.1.0","info":{"title":"ResearchEquals API","description":"API for the ResearchEquals research platform","contact":{"name":"ResearchEquals Team","email":"TBD@researchequals.com"},"license":{"name":""},"version":"0.1.0"},"servers":[{"url":"http://localhost:8080","description":"Development server"},{"url":"https://researchequals.com/api","description":"Production server"}],"paths":{"/admin/update-output-metadata":{"post":{"tags":["Admin"],"summary":"Regenerate and resubmit DOI metadata XML for all published versions of a specific output.\nAll versions are submitted as components in a single Crossref batch. Admin only.","operationId":"update_output_metadata","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOutputMetadataRequest"}}},"required":true},"responses":{"200":{"description":"Successfully updated output metadata"},"403":{"description":"Forbidden - Admin role required"},"404":{"description":"Output not found"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/affiliations":{"get":{"tags":["Affiliations"],"summary":"List all affiliations","operationId":"get_affiliations","parameters":[{"name":"page","in":"query","description":"Page number for pagination (default: 1)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Number of items per page (default: 10, max: 100)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"user_id","in":"query","description":"Filter affiliations by user ID","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of affiliations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedAffiliationsResponse"}}}},"500":{"description":"Internal server error"}}},"post":{"tags":["Affiliations"],"summary":"Create new affiliation","operationId":"post_affiliation","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAffiliation"}}},"required":true},"responses":{"201":{"description":"Affiliation created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AffiliationResponse"}}}},"400":{"description":"Bad request (invalid ROR ID or ROR API error)"},"401":{"description":"Unauthorized (not logged in)"},"403":{"description":"Forbidden (can only create affiliations for yourself or as admin)"},"404":{"description":"User not found"},"409":{"description":"Conflict (user already linked to this organization)"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/affiliations/{affiliation_id}":{"delete":{"tags":["Affiliations"],"summary":"Delete an affiliation","operationId":"delete_affiliation","parameters":[{"name":"affiliation_id","in":"path","description":"Affiliation identifier (uuid)","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No content, successful delete"},"401":{"description":"Unauthorized (not logged in)"},"403":{"description":"Forbidden (insufficient permissions)"},"404":{"description":"Affiliation not found"}},"security":[{"cookie_auth":[]}]}},"/auth/invitation":{"post":{"tags":["Authentication"],"summary":"Invite a new contributor, regardless of having an existing account","operationId":"invite_user","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidatedInvitation"}}},"required":true},"responses":{"200":{"description":"Invitation created"},"400":{"description":"Bad request (invalid invitation)"},"404":{"description":"Invitation not found"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/auth/invitation/accept":{"post":{"tags":["Authentication"],"summary":"Accept invitation","operationId":"accept_invitation","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AcceptInvitation"}}},"required":true},"responses":{"201":{"description":"Invitation accepted"},"400":{"description":"Bad request (invalid invitation)"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/auth/invitation/decline":{"post":{"tags":["Authentication"],"summary":"Decline invitation","operationId":"decline_invitation","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeclineInvitation"}}},"required":true},"responses":{"201":{"description":"Invitation declined"},"400":{"description":"Bad request (invalid invitation)"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/auth/invitation/{token}":{"get":{"tags":["Authentication"],"summary":"Get invitation details from id","operationId":"get_invitation_info","parameters":[{"name":"token","in":"path","description":"Invitation identifier (token)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Invitation info","content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationClaims"}}}},"400":{"description":"Bad request (invalid invitation)"},"500":{"description":"Internal server error"}}}},"/auth/login":{"post":{"tags":["Authentication"],"summary":"Login with email/password - returns JWT or OTP challenge","operationId":"login_step1","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginCredentials"}}},"required":true},"responses":{"200":{"description":"Login successful. Access and refresh tokens set as HttpOnly cookies, or OTP challenge returned","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"},"examples":{"otp_challenge":{"summary":"2FA required","value":{"message":"OTP verification required","otp_login_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...","requires_otp":true}},"successful_login":{"summary":"Successful login without 2FA","value":{"message":"Login successful"}}}}}},"401":{"description":"Invalid credentials"},"500":{"description":"Internal server error"}}}},"/auth/login-otp":{"post":{"tags":["Authentication"],"summary":"OTP verification as part of the login procedure","operationId":"login_step2_verify_otp","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtpLoginRequest"}}},"required":true},"responses":{"200":{"description":"OTP verification successful - login complete. Access and refresh tokens set as HttpOnly cookies","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"401":{"description":"Invalid OTP code or invalid/expired OTP login token"},"500":{"description":"Internal server error"}}}},"/auth/logout":{"post":{"tags":["Authentication"],"summary":"Logout a specific refresh token (single device logout)","operationId":"logout","responses":{"200":{"description":"Logged out successfully. Both access and refresh token cookies cleared","content":{"text/plain":{"schema":{"type":"string"},"example":{"message":"Logged out successfully"}}}},"401":{"description":"Invalid or expired refresh token or cookie not found"},"500":{"description":"Internal server error"}}}},"/auth/oidc/{provider}/callback":{"get":{"tags":["Authentication"],"summary":"Handle OIDC callback and complete authentication","operationId":"oidc_callback","parameters":[{"name":"provider","in":"path","description":"OIDC provider name","required":true,"schema":{"type":"string"}},{"name":"code","in":"query","description":"OIDC callback code","required":true,"schema":{"type":"string"}},{"name":"state","in":"query","description":"OIDC callback state","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OIDC login complete"},"400":{"description":"OIDC bad request"},"500":{"description":"Internal server error"}}}},"/auth/oidc/{provider}/callback-connect":{"get":{"tags":["Authentication"],"summary":"Handle OIDC callback to connect to logged in account","operationId":"oidc_callback_connect","parameters":[{"name":"provider","in":"path","description":"OIDC provider name","required":true,"schema":{"type":"string"}},{"name":"code","in":"query","description":"OIDC callback code","required":true,"schema":{"type":"string"}},{"name":"state","in":"query","description":"OIDC callback state","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OIDC connection complete. Returns subject claim."},"400":{"description":"OIDC bad request"},"500":{"description":"Internal server error"}}}},"/auth/oidc/{provider}/init":{"get":{"tags":["Authentication"],"summary":"Initiate OIDC login flow","operationId":"oidc_login","parameters":[{"name":"provider","in":"path","description":"OIDC provider name","required":true,"schema":{"type":"string"}},{"name":"action","in":"query","description":"Indicate what OIDC action to take (connect, signup; defaults to login if none provided)","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OIDC login returned"},"500":{"description":"Internal server error"}}}},"/auth/otp/disable":{"post":{"tags":["Authentication"],"summary":"Disable 2FA for the user account of the web token","operationId":"disable_otp","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtpVerificationRequest"}}},"required":true},"responses":{"200":{"description":"OTP disabled successfully","content":{"text/plain":{"schema":{"type":"string"},"example":{"message":"OTP disabled successfully"}}}},"400":{"description":"Validation error or OTP not configured"},"401":{"description":"Invalid OTP code or unauthorized"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/auth/otp/generate":{"post":{"tags":["Authentication"],"summary":"Generate a base secret for enabling 2FA","operationId":"generate_otp","responses":{"200":{"description":"OTP generated successfully","content":{"text/plain":{"schema":{"type":"string"},"example":{"base32":"JBSWY3DPEHPK3PXP","otpauth_url":"otpauth://totp/ResearchEquals:user@example.com?secret=JBSWY3DPEHPK3PXP&issuer=ResearchEquals"}}}},"400":{"description":"Invalid user ID"},"401":{"description":"Unauthorized"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/auth/otp/verify":{"post":{"tags":["Authentication"],"summary":"Verify a OTP from the base secret, to enable 2FA","operationId":"verify_otp","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OtpVerificationRequest"}}},"required":true},"responses":{"200":{"description":"OTP verified successfully","content":{"text/plain":{"schema":{"type":"string"},"example":{"message":"OTP verified successfully","verified":true}}}},"400":{"description":"Validation error or OTP not configured"},"401":{"description":"Invalid OTP code or unauthorized"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/auth/refresh":{"get":{"tags":["Authentication"],"summary":"Access token rotation using refresh token from HttpOnly cookie","operationId":"refresh_access_token","responses":{"200":{"description":"Tokens refreshed successfully. New access and refresh tokens set as HttpOnly cookies","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RefreshResponse"}}}},"401":{"description":"Invalid or expired refresh token or cookie not found"},"500":{"description":"Internal server error"}}}},"/auth/register":{"post":{"tags":["Authentication"],"summary":"Register a new user account","operationId":"register_user","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidatedUserRegistration"}}},"required":true},"responses":{"201":{"description":"User registered successfully. Access and refresh tokens set as HttpOnly cookies","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoginResponse"}}}},"400":{"description":"Validation error"},"409":{"description":"Email already registered"},"500":{"description":"Internal server error"}}}},"/auth/register-invitation":{"post":{"tags":["Authentication"],"summary":"Accept invitation to a new user","operationId":"register_invited_user","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InvitationRegistration"}}},"required":true},"responses":{"201":{"description":"Registration created based on invitation"},"400":{"description":"Bad request (invalid invitation)"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/auth/request-reset":{"post":{"tags":["Authentication"],"summary":"Request password reset by sending reset token to user's email","operationId":"request_password_reset","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestPasswordResetRequest"}}},"required":true},"responses":{"200":{"description":"Password reset request processed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/RequestPasswordResetResponse"}}}},"500":{"description":"Failed to generate reset token, email service configuration error, or service unavailable"}},"security":[{"cookie_auth":[]}]}},"/auth/reset-password":{"get":{"tags":["Authentication"],"summary":"Validate a password reset token","operationId":"validate_reset_token","parameters":[{"name":"token","in":"query","description":"Password reset token to validate","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Reset token validation result","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidateResetTokenResponse"}}}},"400":{"description":"Invalid or expired reset token"},"500":{"description":"Server configuration error or service unavailable"}}},"post":{"tags":["Authentication"],"summary":"Reset password using valid reset token","operationId":"reset_password","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordRequest"}}},"required":true},"responses":{"200":{"description":"Password reset successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ResetPasswordResponse"}}}},"400":{"description":"Password validation error or invalid/expired reset token"},"500":{"description":"Server configuration error or service unavailable"}}}},"/auth/revoke-all-sessions":{"post":{"tags":["Authentication"],"summary":"Revoke all refresh tokens for the user (logout from all devices)","operationId":"revoke_all_sessions","responses":{"200":{"description":"All sessions revoked successfully","content":{"text/plain":{"schema":{"type":"string"},"example":{"message":"All sessions revoked successfully"}}}},"400":{"description":"Invalid user ID"},"401":{"description":"Unauthorized - Invalid or missing access token cookie"},"500":{"description":"Failed to revoke sessions or internal server error"}},"security":[{"cookie_auth":[]}]}},"/auth/update-password":{"post":{"tags":["Authentication"],"summary":"Update password for the authenticated user","operationId":"update_password","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePasswordRequest"}}},"required":true},"responses":{"200":{"description":"Password updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdatePasswordResponse"}}}},"400":{"description":"Validation error - password too short"},"401":{"description":"Current password is incorrect or unauthorized"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/auth/verify-email":{"get":{"tags":["Authentication"],"summary":"Verify an email using the HMAC token (GET request with query parameter)","operationId":"verify_email","parameters":[{"name":"token","in":"query","description":"HMAC email verification token","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Email verified successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VerifyEmailResponse"}}}},"400":{"description":"Invalid or expired verification token or user not found"},"500":{"description":"Server configuration error or service unavailable"}}},"post":{"tags":["Authentication"],"summary":"Resend email verification to the logged in user","operationId":"resend_verification_email","responses":{"200":{"description":"Verification email resent successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SendVerificationResponse"}}}},"400":{"description":"Email is already verified or user not found"},"500":{"description":"Failed to generate verification token, email service configuration error, or service unavailable"}},"security":[{"cookie_auth":[]}]}},"/collection/{cid}":{"get":{"tags":["Collections"],"summary":"Get collection with latest issue details","operationId":"get_collection","parameters":[{"name":"cid","in":"path","description":"Collection ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Collection with latest issue details (contributors, submissions, pids)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionWithIssueDetails"}}}}}}},"/collections":{"get":{"tags":["Collections"],"summary":"List all outputs (paginated)","operationId":"get_collections","parameters":[{"name":"page","in":"query","description":"Page number for pagination (default: 1)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Number of items per page (default: 10, max: 100)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"query","in":"query","description":"Fuzzy search across collection title and description","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of collections","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedCollectionsResponse"}}}},"500":{"description":"Internal server error"}}},"post":{"tags":["Collections"],"summary":"Create a new collection with first issue, linked to the current account","operationId":"create_collection","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateCollectionRequest"}}},"required":true},"responses":{"201":{"description":"Created collection for current account with issue 1","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CollectionWithIssues"}}}},"500":{"description":"Internal Server Error"}},"security":[{"cookie_auth":[]}]}},"/contributors":{"post":{"tags":["Contributors"],"summary":"Create new contributor","operationId":"create_contributor_endpoint","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateContributorRequest"}}},"required":true},"responses":{"201":{"description":"Contributor created"},"409":{"description":"Contributor conflict (for example, duplicate)"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/contributors/{id}":{"get":{"tags":["Contributors"],"summary":"Get contributor information by ID","operationId":"get_contributor","parameters":[{"name":"id","in":"path","description":"Contributor id (uuid)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Contributor information retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ContributorResponse"}}}},"404":{"description":"Contributor not found"}},"security":[{"cookie_auth":[]}]},"put":{"tags":["Contributors"],"summary":"Update contributor information by ID","operationId":"update_contributor","parameters":[{"name":"id","in":"path","description":"Contributor id (uuid)","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateContributorRequest"}}},"required":true},"responses":{"200":{"description":"Contributor updated successfully"},"401":{"description":"No privileges (not authenticated)"},"403":{"description":"Insufficient privileges (forbidden)"},"404":{"description":"Contributor not found"},"500":{"description":"Server configuration error or service unavailable"}},"security":[{"cookie_auth":[]}]},"delete":{"tags":["Contributors"],"summary":"Delete contributor information by ID","operationId":"delete_contributor","parameters":[{"name":"id","in":"path","description":"Contributor id (uuid)","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Contributor deleted"},"404":{"description":"Contributor not found"}},"security":[{"cookie_auth":[]}]}},"/drafts":{"get":{"tags":["Outputs"],"summary":"Get the drafts for the current account","operationId":"get_drafts","responses":{"200":{"description":"List of draft versions for the current account","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Version"}}}}},"500":{"description":"Internal Server Error"}},"security":[{"cookie_auth":[]}]}},"/edges":{"get":{"tags":["Edges"],"summary":"List edges filtered by origin link URL","operationId":"get_edges","parameters":[{"name":"origin_url","in":"query","description":"Filter by origin link URL","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of edges with link and user information","content":{"application/json":{"schema":{"$ref":"#/components/schemas/EdgesListResponse"}}}},"400":{"description":"Bad request (must provide origin_url)"},"500":{"description":"Internal server error"}}},"post":{"tags":["Edges"],"summary":"Create a new edge between two URLs","description":"This endpoint:\n1. Canonicalizes both URLs\n2. Fetches metadata for both URLs\n3. Archives both URLs\n4. Creates links for both URLs if they don't exist\n5. Creates the edge linking them together","operationId":"create_edge","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEdgeRequest"}}},"required":true},"responses":{"201":{"description":"Edge created successfully with link metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateEdgeResponse"}}}},"400":{"description":"Bad request (missing or invalid URLs)"},"401":{"description":"Unauthorized (not logged in)"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/editing":{"get":{"tags":["Collections"],"summary":"Get the collections for the current account","operationId":"get_editing","responses":{"200":{"description":"List of collection issues currently being curated for the current account","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/Issue"}}}}},"500":{"description":"Internal Server Error"}},"security":[{"cookie_auth":[]}]}},"/files/{file_key}":{"get":{"tags":["Storage"],"summary":"Get presigned URL from storage provider and send a tmp redirect","operationId":"get_presigned_url","parameters":[{"name":"file_key","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"307":{"description":""},"500":{"description":""}}}},"/issues/{issue_id}":{"get":{"tags":["Issues"],"summary":"Get an issue with its submissions and links. Returns public issues to everyone, or non-public issues to editors only.","operationId":"get_issue","parameters":[{"name":"issue_id","in":"path","description":"Issue identifier (uuid)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Issue with submissions","content":{"application/json":{"schema":{"$ref":"#/components/schemas/IssueWithSubmissions"}}}},"404":{"description":"Issue not found"},"500":{"description":"Internal server error"}},"security":[{},{"cookie_auth":[]}]},"put":{"tags":["Issues"],"summary":"Update a collection issue","operationId":"update_issue","parameters":[{"name":"issue_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateIssueRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Issue"}}}},"404":{"description":""},"500":{"description":""}},"security":[{"cookie_auth":[]}]},"delete":{"tags":["Issues"],"summary":"Delete an issue (only if not public and not published)","operationId":"delete_issue","parameters":[{"name":"issue_id","in":"path","description":"Issue identifier (uuid)","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Issue deleted successfully"},"403":{"description":"Forbidden - cannot delete public or published issues"},"404":{"description":"Issue not found"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/issues/{issue_id}/header":{"post":{"tags":["Issues"],"summary":"Upload header image for an issue","operationId":"upload_issue_header","parameters":[{"name":"issue_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"description":"Binary image data","content":{"application/octet-stream":{"schema":{"type":"array","items":{"type":"integer","format":"int32","minimum":0}}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadResponse"}}}},"400":{"description":""},"403":{"description":""},"404":{"description":""},"500":{"description":""}},"security":[{"cookie_auth":[]}]}},"/issues/{issue_id}/icon":{"post":{"tags":["Issues"],"summary":"Upload icon image for an issue","operationId":"upload_issue_icon","parameters":[{"name":"issue_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"description":"Binary image data","content":{"application/octet-stream":{"schema":{"type":"array","items":{"type":"integer","format":"int32","minimum":0}}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadResponse"}}}},"400":{"description":""},"403":{"description":""},"404":{"description":""},"500":{"description":""}},"security":[{"cookie_auth":[]}]}},"/issues/{issue_id}/invitations":{"get":{"tags":["Issues"],"summary":"Get all invitations for a specific version","operationId":"get_issue_invites","parameters":[{"name":"issue_id","in":"path","description":"Issue ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of invitations for the issue","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/InvitationResponse"}}}}},"403":{"description":"Forbidden - User does not have access to this issue"},"404":{"description":"issue not found"}},"security":[{"cookie_auth":[]}]}},"/issues/{issue_id}/publish":{"post":{"tags":["Issues"],"summary":"Publish an issue (editors only) - sets public to true and published_at to current timestamp","operationId":"publish_issue","parameters":[{"name":"issue_id","in":"path","description":"Issue identifier (uuid)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Issue published successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Issue"}}}},"403":{"description":"Forbidden - user is not an editor"},"404":{"description":"Issue not found"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/issues/{issue_id}/submit":{"post":{"tags":["Submissions"],"summary":"Submit a link to an issue","operationId":"submit_link_to_issue","parameters":[{"name":"issue_id","in":"path","description":"Issue identifier (uuid)","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmitLinkRequest"}}},"required":true},"responses":{"201":{"description":"Submission created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmissionResponse"}}}},"400":{"description":"Bad request"},"401":{"description":"Unauthorized (not logged in)"},"404":{"description":"Issue not found"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/licenses":{"get":{"tags":["Licenses"],"summary":"Get all licenses","operationId":"get_licenses","responses":{"200":{"description":"List of all licenses","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LicensesResponse"}}}},"500":{"description":"Internal server error"}}}},"/links":{"get":{"tags":["Links"],"summary":"List links, optional polymorphic filtering","operationId":"get_links","parameters":[{"name":"reference_type","in":"query","description":"Filter by reference type (user, organization)","required":false,"schema":{"$ref":"#/components/schemas/ReferenceType"}},{"name":"reference_id","in":"query","description":"Filter by reference id","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of links","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinksListResponse"}}}},"500":{"description":"Internal server error"}}},"post":{"tags":["Links"],"summary":"Create a new link for a polymorphic reference","operationId":"post_link","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PostLink"}}},"required":true},"responses":{"201":{"description":"Link created successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkResponse"}}}},"400":{"description":"Bad request (validation error)"},"401":{"description":"Unauthorized (not logged in)"},"403":{"description":"Forbidden (insufficient permissions)"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/links/{id}":{"put":{"tags":["Links"],"summary":"Update link metadata (title, image_url) for issue links - only if currently null and only by editors","operationId":"put_link","parameters":[{"name":"id","in":"path","description":"Link identifier (uuid)","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PutLink"}}},"required":true},"responses":{"200":{"description":"Link metadata updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/LinkResponse"}}}},"400":{"description":"Bad request (field is not empty, no fields provided, or not an issue link)"},"401":{"description":"Unauthorized (not logged in)"},"403":{"description":"Forbidden (must be an editor on the issue)"},"404":{"description":"Link not found"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]},"delete":{"tags":["Links"],"summary":"Delete an existing link, based on link id","operationId":"delete_link","parameters":[{"name":"id","in":"path","description":"Link identifier (uuid)","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"No content, successful delete"},"401":{"description":"Unauthorized (not logged in)"},"403":{"description":"Forbidden (insufficient permissions)"},"404":{"description":"Link not found"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/organizations":{"get":{"tags":["Organizations"],"summary":"List all organizations","operationId":"get_organizations","parameters":[{"name":"page","in":"query","description":"Page number for pagination (default: 1)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Number of items per page (default: 10, max: 100)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"query","in":"query","description":"Fuzzy search across name and ror","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of organizations","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedOrganizationsResponse"}}}},"500":{"description":"Internal server error"}}},"post":{"tags":["Organizations"],"summary":"Create an organization based on a ROR id","operationId":"create_organization","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOrganizationRequest"}}},"required":true},"responses":{"200":{"description":"Organization successfully created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationResponse"}}}},"409":{"description":"Organization already exists (conflict)"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/organizations/slug/{slug}":{"get":{"tags":["Organizations"],"summary":"Find an organization by {slug}","operationId":"get_organization_by_slug","parameters":[{"name":"slug","in":"path","description":"Organization slug (based on ROR number or manual entry)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Organization successfully retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationWithLinksAndPeopleResponse"}}}},"404":{"description":"Organization not found"}}}},"/organizations/{id}":{"get":{"tags":["Organizations"],"summary":"Find an organization by {id}","operationId":"get_organization","parameters":[{"name":"id","in":"path","description":"Organization id (uuid)","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Organization successfully retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationResponse"}}}},"404":{"description":"Organization not found"}}},"put":{"tags":["Organizations"],"summary":"Administrative route to update an organization's information","operationId":"update_organization","parameters":[{"name":"id","in":"path","description":"Organization id (uuid)","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateOrganization"}}},"required":true},"responses":{"200":{"description":"Organization updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrganizationResponse"}}}},"400":{"description":"Bad update request (check schema)"},"404":{"description":"Organization not found"},"409":{"description":"Organization already exists"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]},"delete":{"tags":["Organizations"],"summary":"Administrative route to delete an organization by id","operationId":"delete_organization","parameters":[{"name":"id","in":"path","description":"Organization id","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Organization deleted successfully"},"404":{"description":"Organization not found"}},"security":[{"cookie_auth":[]}]}},"/organizations/{organization_id}/link/{user_id}":{"post":{"tags":["Organizations"],"summary":"Create an affiliation between {organization_id}-{user_id}","operationId":"link_user_to_organization","parameters":[{"name":"organization_id","in":"path","description":"Organization ID","required":true,"schema":{"type":"string"}},{"name":"user_id","in":"path","description":"User ID","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"Affiliation created","content":{"application/json":{"schema":{"$ref":"#/components/schemas/AffiliationResponse"}}}},"404":{"description":"Organization or user not found"},"409":{"description":"Existing affiliation for user to organization"}},"security":[{"cookie_auth":[]}]}},"/outputs":{"get":{"tags":["Outputs"],"summary":"List all outputs (paginated)","operationId":"get_outputs","parameters":[{"name":"page","in":"query","description":"Page number for pagination (default: 1)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Number of items per page (default: 10, max: 100)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"query","in":"query","description":"Fuzzy search across output title and description","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of outputs","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedOutputsResponse"}}}},"500":{"description":"Internal server error"}}},"post":{"tags":["Outputs"],"summary":"Create a new output with version, linked to the current account","operationId":"create_output","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateOutputRequest"}}},"required":true},"responses":{"201":{"description":"Created output for current account with version 1","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutputWithVersions"}}}},"500":{"description":"Internal Server Error"}},"security":[{"cookie_auth":[]}]}},"/outputs/types":{"get":{"tags":["Outputs"],"summary":"Get all available output types","operationId":"get_output_types","responses":{"200":{"description":"List of all output types","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutputTypesResponse"}}}},"500":{"description":"Internal server error"}}}},"/outputs/{oid}":{"get":{"tags":["Outputs"],"summary":"Get an outputs latest information","operationId":"get_output","parameters":[{"name":"oid","in":"path","description":"Output ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Output with latest version retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/OutputWithVersions"}}}}}},"post":{"tags":["Outputs"],"summary":"Create a new version for output {oid}","operationId":"create_version","parameters":[{"name":"oid","in":"path","description":"Output ID","required":true,"schema":{"type":"string"}}],"responses":{"201":{"description":"New version created for output","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Version"}}}},"500":{"description":"Internal Server Error"}},"security":[{"cookie_auth":[]}]},"delete":{"tags":["Outputs"],"summary":"Delete an output identified by {oid}. Only possible if no versions exist","operationId":"delete_output","parameters":[{"name":"oid","in":"path","description":"Output ID","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"Output successfully deleted"},"404":{"description":"Output not found"},"409":{"description":"Output not deleted, versions still exist (conflict)"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/submissions/{id}":{"put":{"tags":["Submissions"],"summary":"Update submission","description":"- Anyone who created the submission can update the comment\n- Editors and admins can update comment, status, and position","operationId":"update_submission_comment","parameters":[{"name":"id","in":"path","description":"Submission identifier (uuid)","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSubmissionRequest"}}},"required":true},"responses":{"200":{"description":"Submission updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubmissionResponse"}}}},"401":{"description":"Unauthorized (not logged in)"},"403":{"description":"Forbidden (not authorized to update this submission or field)"},"404":{"description":"Submission not found"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/upload":{"post":{"tags":["Storage"],"summary":"Upload a file to the configured storage provider","operationId":"upload_file","requestBody":{"description":"Binary file data","content":{"application/octet-stream":{"schema":{"type":"array","items":{"type":"integer","format":"int32","minimum":0}}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadResponse"}}}},"400":{"description":""},"500":{"description":""}},"security":[{"cookie_auth":[]}]}},"/upload/avatar":{"post":{"tags":["Storage"],"summary":"Upload avatar to storage provider and link to user","operationId":"upload_avatar","requestBody":{"description":"Binary file data","content":{"application/octet-stream":{"schema":{"type":"array","items":{"type":"integer","format":"int32","minimum":0}}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UploadResponse"}}}},"400":{"description":""},"404":{"description":""},"500":{"description":""}},"security":[{"cookie_auth":[]}]}},"/upload/delete/{file_key}":{"delete":{"tags":["Storage"],"summary":"Delete file key from storage provider and database","operationId":"delete_file","parameters":[{"name":"file_key","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":""},"403":{"description":""},"404":{"description":""},"500":{"description":""}},"security":[{"cookie_auth":[]}]}},"/user/profile":{"get":{"tags":["Authentication"],"summary":"Get the logged in user information","operationId":"get_user_profile","responses":{"200":{"description":"User profile retrieved successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"400":{"description":"Invalid user ID"},"401":{"description":"Unauthorized - Invalid or missing access token cookie"},"404":{"description":"User not found"},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/users":{"get":{"tags":["Users"],"summary":"List all users' public information","operationId":"get_users","parameters":[{"name":"page","in":"query","description":"Page number for pagination (default: 1)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"per_page","in":"query","description":"Number of items per page (default: 10, max: 100)","required":false,"schema":{"type":"integer","format":"int64"}},{"name":"query","in":"query","description":"Fuzzy search across username, given_name, surname, and bio","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"Paginated list of users","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PaginatedUsersResponse"}}}},"500":{"description":"Internal server error"}}}},"/users/@{username}":{"get":{"tags":["Users"],"summary":"Get username's public information","operationId":"get_user_by_username","parameters":[{"name":"username","in":"path","description":"Username to retrieve","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"User found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicUserJoinResponse"}}}},"404":{"description":"User not found","content":{"application/json":{"schema":{"type":"object"},"example":{"error":"User not found"}}}},"500":{"description":"Internal server error"}}}},"/users/{id}":{"get":{"tags":["Users"],"summary":"Get user id's public information","operationId":"get_user","parameters":[{"name":"id","in":"path","description":"User ID to retrieve","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"User found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/PublicUserResponse"}}}},"401":{"description":"Unauthorized"},"404":{"description":"User not found","content":{"application/json":{"schema":{"type":"object"},"example":{"error":"User not found"}}}},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]},"put":{"tags":["Users"],"summary":"Update a user's information, as identified by their {id}","operationId":"update_user","parameters":[{"name":"id","in":"path","description":"User ID to update","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateUser"}}},"required":true},"responses":{"200":{"description":"User updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UserResponse"}}}},"400":{"description":"Bad request - no fields provided or validation error","content":{"application/json":{"schema":{"type":"object"},"example":{"error":"No fields provided for update"}}}},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - can only update your own profile","content":{"application/json":{"schema":{"type":"object"},"example":{"error":"Can only update your own profile"}}}},"404":{"description":"User not found","content":{"application/json":{"schema":{"type":"object"},"example":{"error":"User not found"}}}},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]},"delete":{"tags":["Users"],"summary":"Delete the user linked to {id} after self-authorization","operationId":"delete_user","parameters":[{"name":"id","in":"path","description":"User ID to delete","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":"User deleted successfully"},"401":{"description":"Unauthorized"},"403":{"description":"Forbidden - insufficient permissions"},"404":{"description":"User not found","content":{"application/json":{"schema":{"type":"object"},"example":{"error":"User not found"}}}},"500":{"description":"Internal server error"}},"security":[{"cookie_auth":[]}]}},"/versions/{version_id}":{"get":{"tags":["Versions"],"summary":"Get a specific version","operationId":"get_version","parameters":[{"name":"version_id","in":"path","description":"Version ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Version retrieved","content":{"application/json":{"schema":{"$ref":"#/components/schemas/VersionWithContributors"}}}}}},"put":{"tags":["Versions"],"summary":"Update a version record","operationId":"update_version","parameters":[{"name":"version_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateVersionRequest"}}},"required":true},"responses":{"200":{"description":"","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Version"}}}},"404":{"description":""},"500":{"description":""}},"security":[{"cookie_auth":[]}]},"delete":{"tags":["Versions"],"summary":"Delete a version record","operationId":"delete_version","parameters":[{"name":"version_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"204":{"description":""},"404":{"description":""},"500":{"description":""}},"security":[{"cookie_auth":[]}]}},"/versions/{version_id}/invitations":{"get":{"tags":["Versions"],"summary":"Get all invitations for a specific version","operationId":"get_version_invites","parameters":[{"name":"version_id","in":"path","description":"Version ID","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"List of invitations for the version","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/InvitationResponse"}}}}},"403":{"description":"Forbidden - User does not have access to this version"},"404":{"description":"Version not found"}},"security":[{"cookie_auth":[]}]}}},"components":{"schemas":{"AcceptInvitation":{"type":"object","required":["token"],"properties":{"given_name":{"type":["string","null"]},"surname":{"type":["string","null"]},"token":{"type":"string"},"username":{"type":["string","null"]}}},"AffiliationResponse":{"type":"object","required":["id","created_at","updated_at","user_id","organization_id"],"properties":{"created_at":{"type":"string","format":"date-time"},"id":{"type":"string"},"organization_id":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"user_id":{"type":"string"}}},"AffiliationWithOrganization":{"type":"object","required":["id","created_at","updated_at","user_id","organization_id","organization_name"],"properties":{"created_at":{"type":"string","format":"date-time"},"id":{"type":"string"},"organization_id":{"type":"string"},"organization_name":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"user_id":{"type":"string"}}},"Collection":{"type":"object","required":["id","created_at","updated_at","title"],"properties":{"abbrev_title":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"description":{"type":["string","null"]},"id":{"type":"string"},"title":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"CollectionWithIssueDetails":{"allOf":[{"$ref":"#/components/schemas/Collection"},{"$ref":"#/components/schemas/Issue"},{"type":"object","required":["contributors","submissions","pids"],"properties":{"contributors":{"type":"array","items":{"$ref":"#/components/schemas/ContributorWithUser"}},"pids":{"type":"array","items":{"type":"string"}},"submissions":{"type":"array","items":{"$ref":"#/components/schemas/SubmissionWithLink"}}}}]},"CollectionWithIssues":{"allOf":[{"$ref":"#/components/schemas/Collection"},{"$ref":"#/components/schemas/IssueFields"}]},"ContributorResponse":{"type":"object","required":["id","created_at","updated_at","user_id","reference_type","reference_id","role","position","consent_to_publish"],"properties":{"consent_to_publish":{"type":"boolean"},"created_at":{"type":"string","format":"date-time"},"id":{"type":"string"},"position":{"type":"integer","format":"int32"},"reference_id":{"type":"string"},"reference_type":{"type":"string"},"role":{"$ref":"#/components/schemas/ContributorsRole"},"updated_at":{"type":"string","format":"date-time"},"user_id":{"type":"string"}}},"ContributorWithUser":{"type":"object","required":["role","position","given_name","surname","username"],"properties":{"given_name":{"type":"string"},"orcid":{"type":["string","null"]},"position":{"type":"integer","format":"int32"},"role":{"$ref":"#/components/schemas/ContributorsRole"},"surname":{"type":"string"},"username":{"type":"string"}}},"ContributorsRole":{"type":"string","enum":["author","editor","reviewer"]},"CreateAffiliation":{"type":"object","required":["ror","user_id"],"properties":{"ror":{"type":"string"},"user_id":{"type":"string"}}},"CreateCollectionRequest":{"type":"object","required":["title"],"properties":{"abbrev_title":{"type":["string","null"]},"description":{"type":["string","null"]},"title":{"type":"string"}},"example":{"abbrev_title":"MRC","description":"A collection of research outputs","title":"My Research Collection"}},"CreateContributorRequest":{"type":"object","required":["user_id","reference_type","reference_id"],"properties":{"reference_id":{"type":"string"},"reference_type":{"type":"string"},"role":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ContributorsRole"}]},"user_id":{"type":"string"}}},"CreateEdgeRequest":{"type":"object","required":["origin_url","destination_url"],"properties":{"destination_url":{"type":"string"},"origin_url":{"type":"string"}}},"CreateEdgeResponse":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}}},"CreateOrganizationRequest":{"type":"object","required":["ror"],"properties":{"ror":{"type":"string"}}},"CreateOutputRequest":{"type":"object","properties":{"content_s3":{"type":["string","null"]},"description":{"type":["string","null"]},"language":{"type":["string","null"]},"license_id":{"type":["string","null"]},"published":{"type":["boolean","null"]},"refs":{},"supporting_files":{},"title":{"type":["string","null"]},"type_id":{"type":["string","null"]}},"example":{"content_s3":"550e8400-e29b-41d4-a716-446655440000","description":"A groundbreaking study on climate change","published":false,"title":"My Research Paper"}},"DeclineInvitation":{"type":"object","required":["token"],"properties":{"token":{"type":"string"}}},"EdgeWithLinks":{"type":"object","required":["id","created_at","updated_at","user_id","user_given_name","user_surname","user_username","origin_link_id","origin_link_url","origin_link_reference_type","origin_link_reference_id","destination_link_id","destination_link_url","destination_link_reference_type","destination_link_reference_id"],"properties":{"created_at":{"type":"string","format":"date-time"},"destination_link_archive_job_id":{"type":["string","null"]},"destination_link_archive_url":{"type":["string","null"]},"destination_link_description":{"type":["string","null"]},"destination_link_id":{"type":"string"},"destination_link_image_url":{"type":["string","null"]},"destination_link_reference_id":{"type":"string"},"destination_link_reference_type":{"type":"string"},"destination_link_title":{"type":["string","null"]},"destination_link_url":{"type":"string"},"id":{"type":"string"},"origin_link_archive_job_id":{"type":["string","null"]},"origin_link_archive_url":{"type":["string","null"]},"origin_link_description":{"type":["string","null"]},"origin_link_id":{"type":"string"},"origin_link_image_url":{"type":["string","null"]},"origin_link_reference_id":{"type":"string"},"origin_link_reference_type":{"type":"string"},"origin_link_title":{"type":["string","null"]},"origin_link_url":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"user_avatar_s3":{"type":["string","null"]},"user_given_name":{"type":"string"},"user_id":{"type":"string"},"user_surname":{"type":"string"},"user_username":{"type":"string"}}},"EdgesListResponse":{"type":"object","required":["edges"],"properties":{"edges":{"type":"array","items":{"$ref":"#/components/schemas/EdgeWithLinks"}}}},"InvitationClaims":{"type":"object","required":["email","given_name","surname","reference_type","reference_id","exp"],"properties":{"email":{"type":"string"},"exp":{"type":"integer","format":"int64"},"given_name":{"type":"string"},"reference_id":{"type":"string"},"reference_type":{"type":"string"},"surname":{"type":"string"}}},"InvitationRegistration":{"type":"object","required":["token","username","given_name","surname","reference_type","reference_id"],"properties":{"given_name":{"type":"string"},"reference_id":{"type":"string"},"reference_type":{"type":"string"},"surname":{"type":"string"},"token":{"type":"string"},"username":{"type":"string"}}},"InvitationResponse":{"type":"object","required":["id","email","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time"},"email":{"type":"string"},"id":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"Issue":{"type":"object","required":["id","collection_id","created_at","updated_at","public","issue","language","title"],"properties":{"collection_id":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"description":{"type":["string","null"]},"header_s3":{"type":["string","null"]},"icon_s3":{"type":["string","null"]},"id":{"type":"string"},"issue":{"type":"integer","format":"int32"},"language":{"type":"string"},"public":{"type":"boolean"},"published_at":{"type":["string","null"],"format":"date-time"},"subtitle":{"type":["string","null"]},"title":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"volume":{"type":["string","null"]}}},"IssueFields":{"type":"object","required":["issue_id","public","issue","language","title"],"properties":{"description":{"type":["string","null"]},"header_s3":{"type":["string","null"]},"icon_s3":{"type":["string","null"]},"issue":{"type":"integer","format":"int32"},"issue_id":{"type":"string"},"language":{"type":"string"},"public":{"type":"boolean"},"published_at":{"type":["string","null"],"format":"date-time"},"subtitle":{"type":["string","null"]},"title":{"type":"string"},"volume":{"type":["string","null"]}}},"IssueWithSubmissions":{"allOf":[{"$ref":"#/components/schemas/Issue"},{"type":"object","required":["contributors","submissions","pids"],"properties":{"contributors":{"type":"array","items":{"$ref":"#/components/schemas/ContributorWithUser"}},"pids":{"type":"array","items":{"type":"string"}},"submissions":{"type":"array","items":{"$ref":"#/components/schemas/SubmissionWithLink"}}}}]},"License":{"type":"object","required":["id","created_at","updated_at","wikidata_id","url"],"properties":{"created_at":{"type":"string","format":"date-time"},"id":{"type":"string"},"name":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time"},"url":{"type":"string"},"wikidata_id":{"type":"string"}}},"LicensesResponse":{"type":"object","required":["licenses","total"],"properties":{"licenses":{"type":"array","items":{"$ref":"#/components/schemas/License"}},"total":{"type":"integer","minimum":0}}},"Link":{"type":"object","required":["id","created_at","updated_at","original_url","url","url_source","reference_type","reference_id"],"properties":{"archive_job_id":{"type":["string","null"]},"archive_url":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"description":{"type":["string","null"]},"id":{"type":"string"},"image_url":{"type":["string","null"]},"original_url":{"type":"string"},"reference_id":{"type":"string"},"reference_type":{"type":"string"},"title":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time"},"url":{"type":"string"},"url_source":{"$ref":"#/components/schemas/LinksUrlSource"}}},"LinkResponse":{"type":"object","required":["id","created_at","updated_at","url","reference_type","reference_id"],"properties":{"archive_job_id":{"type":["string","null"]},"archive_url":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"description":{"type":["string","null"]},"id":{"type":"string"},"image_url":{"type":["string","null"]},"reference_id":{"type":"string"},"reference_type":{"type":"string"},"title":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time"},"url":{"type":"string"}}},"LinksListResponse":{"type":"object","required":["links"],"properties":{"links":{"type":"array","items":{"$ref":"#/components/schemas/LinkResponse"}}}},"LinksUrlSource":{"type":"string","enum":["declared","inferred"]},"LoginCredentials":{"type":"object","required":["email","password"],"properties":{"email":{"type":"string"},"password":{"type":"string"}},"example":{"email":"user@example.com","password":"password123"}},"LoginResponse":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}},"example":{"message":"Login successful"}},"Organization":{"type":"object","required":["id","created_at","updated_at","ror","name","slug"],"properties":{"country_code":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"established":{"type":["integer","null"],"format":"int32"},"id":{"type":"string"},"latitude":{"type":["number","null"],"format":"float"},"longitude":{"type":["number","null"],"format":"float"},"name":{"type":"string"},"ror":{"type":"string"},"slug":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"OrganizationResponse":{"type":"object","required":["id","created_at","updated_at","ror","name","slug"],"properties":{"country_code":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"established":{"type":["integer","null"],"format":"int32"},"id":{"type":"string"},"latitude":{"type":["number","null"],"format":"float"},"longitude":{"type":["number","null"],"format":"float"},"name":{"type":"string"},"ror":{"type":"string"},"slug":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"OrganizationWithLinksAndPeopleResponse":{"allOf":[{"$ref":"#/components/schemas/OrganizationResponse"},{"type":"object","required":["links","people","outputs","collections"],"properties":{"collections":{"type":"array","items":{"$ref":"#/components/schemas/CollectionWithIssues"}},"links":{"type":"array","items":{"$ref":"#/components/schemas/Link"}},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/OutputWithVersions"}},"people":{"type":"array","items":{"$ref":"#/components/schemas/PublicUserResponse"}}}}]},"OtpLoginRequest":{"type":"object","required":["otp_login_token","otp_code"],"properties":{"otp_code":{"type":"string"},"otp_login_token":{"type":"string"}},"example":{"otp_code":"123456","otp_login_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."}},"OtpVerificationRequest":{"type":"object","required":["otp_code"],"properties":{"otp_code":{"type":"string"}},"example":{"otp_code":"123456"}},"Output":{"type":"object","required":["id","created_at","updated_at"],"properties":{"created_at":{"type":"string","format":"date-time"},"id":{"type":"string"},"updated_at":{"type":"string","format":"date-time"}}},"OutputType":{"type":"object","required":["id","created_at","updated_at","wikidata_id"],"properties":{"created_at":{"type":"string","format":"date-time"},"id":{"type":"string"},"name":{"type":["string","null"]},"updated_at":{"type":"string","format":"date-time"},"wikidata_id":{"type":"string"}}},"OutputTypesResponse":{"type":"object","required":["output_types","total"],"properties":{"output_types":{"type":"array","items":{"$ref":"#/components/schemas/OutputType"}},"total":{"type":"integer","minimum":0}},"example":{"output_types":[],"total":0}},"OutputWithVersions":{"allOf":[{"$ref":"#/components/schemas/Output"},{"$ref":"#/components/schemas/VersionFields"},{"type":"object","required":["contributors","pids"],"properties":{"content_mediatype":{"type":["string","null"]},"contributors":{"type":"array","items":{"$ref":"#/components/schemas/ContributorWithUser"}},"pids":{"type":"array","items":{"type":"string"}}}}]},"PaginatedAffiliationsResponse":{"type":"object","required":["page","per_page","total_results","total_pages","results"],"properties":{"page":{"type":"integer","format":"int64"},"per_page":{"type":"integer","format":"int64"},"results":{"type":"array","items":{"$ref":"#/components/schemas/AffiliationWithOrganization"}},"total_pages":{"type":"integer","format":"int64"},"total_results":{"type":"integer","format":"int64"}},"example":{"page":1,"per_page":10,"results":[],"total_pages":5,"total_results":42}},"PaginatedCollectionsResponse":{"type":"object","required":["page","per_page","total_results","total_pages","results"],"properties":{"page":{"type":"integer","format":"int64"},"per_page":{"type":"integer","format":"int64"},"results":{"type":"array","items":{"$ref":"#/components/schemas/CollectionWithIssues"}},"total_pages":{"type":"integer","format":"int64"},"total_results":{"type":"integer","format":"int64"}}},"PaginatedOrganizationsResponse":{"type":"object","required":["page","per_page","total_results","total_pages","results"],"properties":{"page":{"type":"integer","format":"int64"},"per_page":{"type":"integer","format":"int64"},"results":{"type":"array","items":{"$ref":"#/components/schemas/Organization"}},"total_pages":{"type":"integer","format":"int64"},"total_results":{"type":"integer","format":"int64"}},"example":{"page":1,"per_page":10,"results":[],"total_pages":5,"total_results":42}},"PaginatedOutputsResponse":{"type":"object","required":["page","per_page","total_results","total_pages","results"],"properties":{"page":{"type":"integer","format":"int64"},"per_page":{"type":"integer","format":"int64"},"results":{"type":"array","items":{"$ref":"#/components/schemas/OutputWithVersions"}},"total_pages":{"type":"integer","format":"int64"},"total_results":{"type":"integer","format":"int64"}},"example":{"page":1,"per_page":10,"results":[],"total_pages":5,"total_results":42}},"PaginatedUsersResponse":{"type":"object","required":["page","per_page","total_results","total_pages","results"],"properties":{"page":{"type":"integer","format":"int64"},"per_page":{"type":"integer","format":"int64"},"results":{"type":"array","items":{"$ref":"#/components/schemas/PublicUserResponse"}},"total_pages":{"type":"integer","format":"int64"},"total_results":{"type":"integer","format":"int64"}},"example":{"page":1,"per_page":10,"results":[],"total_pages":5,"total_results":42}},"PostLink":{"type":"object","required":["url","reference_id","reference_type"],"properties":{"reference_id":{"type":"string"},"reference_type":{"type":"string"},"url":{"type":"string"}}},"PublicUserJoinResponse":{"allOf":[{"$ref":"#/components/schemas/PublicUserResponse"},{"type":"object","required":["organizations","links","outputs","collections"],"properties":{"collections":{"type":"array","items":{"$ref":"#/components/schemas/CollectionWithIssues"}},"links":{"type":"array","items":{"$ref":"#/components/schemas/LinkResponse"}},"organizations":{"type":"array","items":{"$ref":"#/components/schemas/OrganizationResponse"}},"outputs":{"type":"array","items":{"$ref":"#/components/schemas/OutputWithVersions"}}}}]},"PublicUserResponse":{"type":"object","required":["username","given_name","surname"],"properties":{"avatar_s3":{"type":["string","null"]},"bio":{"type":["string","null"]},"given_name":{"type":"string"},"orcid":{"type":["string","null"]},"pronouns":{"type":["string","null"]},"surname":{"type":"string"},"username":{"type":"string"}}},"PutLink":{"type":"object","properties":{"image_url":{"type":["string","null"]},"title":{"type":["string","null"]}}},"RefreshResponse":{"type":"object","description":"Response containing success message only\nBoth access token and refresh token are now set as HttpOnly cookies for security","required":["message"],"properties":{"message":{"type":"string"}},"example":{"message":"Token refreshed successfully"}},"RequestPasswordResetRequest":{"type":"object","required":["email"],"properties":{"email":{"type":"string"}},"example":{"email":"user@example.com"}},"RequestPasswordResetResponse":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}},"example":{"message":"If your email is registered, you will receive a password reset link."}},"ResetPasswordRequest":{"type":"object","required":["token","new_password"],"properties":{"new_password":{"type":"string"},"token":{"type":"string"}},"example":{"new_password":"newpassword123","token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."}},"ResetPasswordResponse":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}},"example":{"message":"Password reset successfully"}},"SendVerificationResponse":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}},"example":{"message":"Verification email sent successfully"}},"SubmissionResponse":{"type":"object","required":["id","created_at","updated_at","issue_id","contributor_id","link_id","status"],"properties":{"comment":{"type":["string","null"]},"contributor_id":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"id":{"type":"string"},"issue_id":{"type":"string"},"link_id":{"type":"string"},"position":{"type":["integer","null"],"format":"int32"},"status":{"$ref":"#/components/schemas/SubmissionsStatus"},"updated_at":{"type":"string","format":"date-time"}}},"SubmissionWithLink":{"type":"object","required":["id","created_at","updated_at","contributor_id","status","link_id","link_url","contributor_given_name","contributor_surname","contributor_username"],"properties":{"comment":{"type":["string","null"]},"contributor_avatar_s3":{"type":["string","null"]},"contributor_given_name":{"type":"string"},"contributor_id":{"type":"string"},"contributor_surname":{"type":"string"},"contributor_username":{"type":"string"},"created_at":{"type":"string","format":"date-time"},"id":{"type":"string"},"link_archive_job_id":{"type":["string","null"]},"link_archive_url":{"type":["string","null"]},"link_description":{"type":["string","null"]},"link_id":{"type":"string"},"link_image_url":{"type":["string","null"]},"link_title":{"type":["string","null"]},"link_url":{"type":"string"},"position":{"type":["integer","null"],"format":"int32"},"status":{"$ref":"#/components/schemas/SubmissionsStatus"},"updated_at":{"type":"string","format":"date-time"}}},"SubmissionsStatus":{"type":"string","enum":["accepted","pending","declined"]},"SubmitLinkRequest":{"type":"object","required":["link"],"properties":{"comment":{"type":["string","null"]},"link":{"type":"string"},"status":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SubmissionsStatus"}]}}},"UpdateContributorRequest":{"type":"object","properties":{"position":{"type":["integer","null"],"format":"int32"},"role":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/ContributorsRole"}]}}},"UpdateIssueRequest":{"type":"object","properties":{"description":{"type":["string","null"]},"header_s3":{"type":["string","null"]},"icon_s3":{"type":["string","null"]},"language":{"type":["string","null"]},"public":{"type":["boolean","null"]},"subtitle":{"type":["string","null"]},"title":{"type":["string","null"]},"volume":{"type":["string","null"]}}},"UpdateOrganization":{"type":"object","properties":{"country_code":{"type":["string","null"]},"established":{"type":["integer","null"],"format":"int32"},"latitude":{"type":["number","null"],"format":"float"},"longitude":{"type":["number","null"],"format":"float"},"name":{"type":["string","null"]},"ror":{"type":["string","null"]},"slug":{"type":["string","null"]}}},"UpdateOutputMetadataRequest":{"type":"object","required":["output_id"],"properties":{"output_id":{"type":"string"}},"example":{"output_id":"550e8400-e29b-41d4-a716-446655440000"}},"UpdatePasswordRequest":{"type":"object","required":["current_password","new_password"],"properties":{"current_password":{"type":"string"},"new_password":{"type":"string"}},"example":{"current_password":"oldpassword123","new_password":"newpassword123"}},"UpdatePasswordResponse":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}},"example":{"message":"Password updated successfully"}},"UpdateSubmissionRequest":{"type":"object","properties":{"comment":{"type":["string","null"]},"position":{"type":["integer","null"],"format":"int32"},"status":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/SubmissionsStatus"}]}}},"UpdateUser":{"type":"object","properties":{"avatar_s3":{"type":["string","null"]},"bio":{"type":["string","null"]},"email":{"type":["string","null"]},"given_name":{"type":["string","null"]},"orcid":{"type":["string","null"]},"pronouns":{"type":["string","null"]},"surname":{"type":["string","null"]},"username":{"type":["string","null"]}},"example":{"avatar_s3":"https://s3.amazonaws.com/bucket/avatar.jpg","bio":"Software developer","email":"user@example.com","given_name":"John","orcid":"0000-0000-0000-0000","pronouns":"he/him","surname":"Doe","username":"newusername"}},"UpdateVersionRequest":{"type":"object","properties":{"content_s3":{"type":["string","null"]},"description":{"type":["string","null"]},"language":{"type":["string","null"]},"license_id":{"type":["string","null"]},"published":{"type":["boolean","null"]},"refs":{},"supporting_files":{},"title":{"type":["string","null"]},"type_id":{"type":["string","null"]}}},"UploadResponse":{"type":"object","required":["success","file_url","file_size","message"],"properties":{"file_id":{"type":["string","null"]},"file_size":{"type":"integer","minimum":0},"file_url":{"type":"string"},"message":{"type":"string"},"success":{"type":"boolean"}}},"UserResponse":{"type":"object","required":["id","created_at","email","email_verified","otp_verified","username","given_name","surname","global_role"],"properties":{"avatar_s3":{"type":["string","null"]},"bio":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"email":{"type":"string"},"email_verified":{"type":"boolean"},"given_name":{"type":"string"},"global_role":{"type":"string"},"id":{"type":"string"},"orcid":{"type":["string","null"]},"otp_verified":{"type":"boolean"},"pronouns":{"type":["string","null"]},"surname":{"type":"string"},"username":{"type":"string"}}},"ValidateResetTokenResponse":{"type":"object","required":["valid","message"],"properties":{"email":{"type":["string","null"]},"message":{"type":"string"},"valid":{"type":"boolean"}},"example":{"email":"user@example.com","message":"Reset token is valid","valid":true}},"ValidatedInvitation":{"type":"object","required":["email","given_name","surname","reference_type","reference_id"],"properties":{"email":{"type":"string"},"given_name":{"type":"string"},"reference_id":{"type":"string"},"reference_type":{"type":"string"},"surname":{"type":"string"}}},"ValidatedUserRegistration":{"type":"object","required":["email","password","username","given_name","surname"],"properties":{"email":{"type":"string"},"given_name":{"type":"string"},"password":{"type":"string"},"surname":{"type":"string"},"username":{"type":"string"}},"example":{"email":"user@example.com","given_name":"John","password":"password123","surname":"Doe","username":"johndoe"}},"Value":{},"VerifyEmailResponse":{"type":"object","required":["message","email_verified"],"properties":{"email_verified":{"type":"boolean"},"message":{"type":"string"}},"example":{"email_verified":true,"message":"Email verified successfully"}},"Version":{"type":"object","required":["id","output_id","version","created_at","updated_at","published","type_id","license_id","language"],"properties":{"content_s3":{"type":["string","null"]},"created_at":{"type":"string","format":"date-time"},"description":{"type":["string","null"]},"id":{"type":"string"},"language":{"type":"string"},"license_id":{"type":"string"},"output_id":{"type":"string"},"published":{"type":"boolean"},"published_at":{"type":["string","null"],"format":"date-time"},"refs":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Value"}]},"supporting_files":{"oneOf":[{"type":"null"},{"$ref":"#/components/schemas/Value"}]},"title":{"type":["string","null"]},"type_id":{"type":"string"},"updated_at":{"type":"string","format":"date-time"},"version":{"type":"integer","format":"int32"}}},"VersionFields":{"type":"object","required":["version_id","version","published","type_id","license_id","language"],"properties":{"content_s3":{"type":["string","null"]},"description":{"type":["string","null"]},"language":{"type":"string"},"license_id":{"type":"string"},"published":{"type":"boolean"},"published_at":{"type":["string","null"],"format":"date-time"},"refs":{},"supporting_files":{},"title":{"type":["string","null"]},"type_id":{"type":"string"},"version":{"type":"integer","format":"int32"},"version_id":{"type":"string"}}},"VersionWithContributors":{"allOf":[{"$ref":"#/components/schemas/Version"},{"type":"object","required":["contributors","pids"],"properties":{"contributors":{"type":"array","items":{"$ref":"#/components/schemas/ContributorWithUser"}},"pids":{"type":"array","items":{"type":"string"}}}}]}},"securitySchemes":{"cookie_auth":{"type":"apiKey","in":"cookie","name":"access_token"}}},"tags":[{"name":"Affiliations","description":"Affiliation management endpoints"},{"name":"Authentication","description":"User authentication and registration endpoints"},{"name":"Collections","description":"Collection management endpoints"},{"name":"Contributors","description":"Contributor management endpoints"},{"name":"Edges","description":"Edge management endpoints"},{"name":"Issues","description":"Collection issues management endpoints"},{"name":"Licenses","description":"License related endpoints"},{"name":"Links","description":"Links related endpoints"},{"name":"Organizations","description":"Organization related endpoints"},{"name":"Outputs","description":"Research output management endpoints"},{"name":"Users","description":"User profile management endpoints"},{"name":"Versions","description":"Version management endpoints"}]}