No session. JSON { password }. A matching password returns { grant: { token, expiresAt } } valid for 15 minutes. A link with no password returns { grant: null }. A wrong password is 401 PASSWORD_INCORRECT. An inactive link is 404 ARTIFACT_NOT_FOUND. A missing or non-JSON body is 400 INVALID_REQUEST before any password throttle is charged. Client failures allow 10 per 10 minutes. Share failures allow 30 per 10 minutes, charged only after a wrong password. An exhausted share is 429 RATE_LIMITED with Retry-After and no hash verification. A saturated Argon2 gate, or a share whose remaining slots are all in flight, is 503 UNLOCK_UNAVAILABLE with Retry-After. This route ignores a leftover session cookie and does not apply the cookie origin guard.
{"docsConfig":{"theme":"mint","$schema":"https://mintlify.com/docs.json","name":"Factrove","description":"Guides and references for Factrove, a self-hostable library for HTML artifacts.","colors":{"primary":"#5e64d6","light":"#858bee","dark":"#5055b6"},"api":{"openapi":"api-reference/openapi.json","examples":{"autogenerate":false}},"seo":{"metatags":{"canonical":"https://factrove.mintlify.app"}},"markdown":{"instructions":"Describe what the running code does. Do not invent hosted pricing, launch dates, or security guarantees. Share and viewer links are a configured base URL plus an artifact path. Show localhost and a placeholder origin such as https://library.example.com."},"styling":{"latex":false},"navigation":{"pages":[]}},"deployment":{"deploymentMetadataValue":{"subdomain":"factrove","hasAudioNarration":false,"actualSubdomain":"factrove","customDomains":[],"gitSource":{"type":"github","owner":"magnificode-ltd","repo":"factrove","deployBranch":"main","contentDirectory":"docs","isPrivate":true,"mountPath":"","label":"","_id":"6ad8f94f4e2c59229c394d72"},"entitlements":{},"buildId":"6af0674099ffa6db6966ee8e","clientVersion":"0.0.4087","searchFilterCounts":[{"language":"default","tag":"API reference","count":23},{"language":"default","tag":"Guides","count":10},{"language":"default","tag":"CLI reference","count":9},{"language":"default","tag":"Commands","count":9},{"language":"default","tag":"Artifacts","count":8},{"language":"default","tag":"Get started","count":6},{"language":"default","tag":"Auth","count":6},{"language":"default","tag":"Shares","count":4},{"language":"default","tag":"Public","count":3},{"language":"default","tag":"Overview","count":1}]},"assistantConfig":{"enableAskAiButton":false,"enableStarterQuestions":false,"enableContextualStarterQuestions":false,"enableAskAiSearchBar":true},"basePath":"","hasChatPermissions":false,"hasWebMcpPermissions":false,"toggles":[{"name":"kill-isr","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-mintlify-slack","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"agent-integrations-settings","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"rbac-expansion","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-pr-grouping","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"custom-prefix","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"analytics-v7","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"user-flows-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"no-publish-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-onboarding","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"llms-txt-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving-live","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"stripTemperatureMiddleware","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"support-platform-pylon-zendesk","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"snapshot-serving","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"instant-rollback","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications-server","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"granular-notifications","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automations-fable","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fixed-ai-action-pricing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"automation-resolve-merge-conflict","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"scoped-publishing","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"mintql","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"page-level-analytics","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-version-history-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"billing-page-v2","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"full-page-search","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workspace-projects","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"assistant-v5","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"fork-pr-previews","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"revalidation-jwt","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-sso-scim","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"hobby-abuse-scan","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"dashboard-inbox","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-signup","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-dual-write","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"workos-enabled","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"approve-review-flow","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"editor-metadata","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"sso-setup-deadline-banner","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"turbopuffer-serve","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"live-agents","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false},{"name":"comment-mode","enabled":true,"variant":{"name":"disabled","enabled":false,"feature_enabled":true},"impressionData":false}],"googleFontsInlined":false},"customCss":[],"page":{"pagePath":"api-reference/public/unlock-a-password-protected-share","slug":"/api-reference/public/unlock-a-password-protected-share","pageMetadata":{"title":"Unlock a password-protected share","description":"No session. JSON `{ password }`. A matching password returns `{ grant: { token, expiresAt } }` valid for 15 minutes. A link with no password returns `{ grant: null }`. A wrong password is `401 PASSWORD_INCORRECT`. An inactive link is `404 ARTIFACT_NOT_FOUND`. A missing or non-JSON body is `400 INVALID_REQUEST` before any password throttle is charged. Client failures allow 10 per 10 minutes. Share failures allow 30 per 10 minutes, charged only after a wrong password. An exhausted share is `429 RATE_LIMITED` with `Retry-After` and no hash verification. A saturated Argon2 gate, or a share whose remaining slots are all in flight, is `503 UNLOCK_UNAVAILABLE` with `Retry-After`. This route ignores a leftover session cookie and does not apply the cookie origin guard.","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json post /api/v1/public/artifacts/{id}/{token}/unlock","href":"/api-reference/public/unlock-a-password-protected-share","autogeneratedByOpenApi":true},"description":{"compiledSource":"\"use strict\";\nconst {jsx: _jsx, jsxs: _jsxs} = arguments[0];\nconst {useMDXComponents: _provideComponents} = arguments[0];\nfunction _createMdxContent(props) {\n const _components = {\n code: \"code\",\n p: \"p\",\n ..._provideComponents(),\n ...props.components\n };\n return _jsxs(_components.p, {\n children: [\"No session. JSON \", _jsx(_components.code, {\n children: \"{ password }\"\n }), \". A matching password returns \", _jsx(_components.code, {\n children: \"{ grant: { token, expiresAt } }\"\n }), \" valid for 15 minutes. A link with no password returns \", _jsx(_components.code, {\n children: \"{ grant: null }\"\n }), \". A wrong password is \", _jsx(_components.code, {\n children: \"401 PASSWORD_INCORRECT\"\n }), \". An inactive link is \", _jsx(_components.code, {\n children: \"404 ARTIFACT_NOT_FOUND\"\n }), \". A missing or non-JSON body is \", _jsx(_components.code, {\n children: \"400 INVALID_REQUEST\"\n }), \" before any password throttle is charged. Client failures allow 10 per 10 minutes. Share failures allow 30 per 10 minutes, charged only after a wrong password. An exhausted share is \", _jsx(_components.code, {\n children: \"429 RATE_LIMITED\"\n }), \" with \", _jsx(_components.code, {\n children: \"Retry-After\"\n }), \" and no hash verification. A saturated Argon2 gate, or a share whose remaining slots are all in flight, is \", _jsx(_components.code, {\n children: \"503 UNLOCK_UNAVAILABLE\"\n }), \" with \", _jsx(_components.code, {\n children: \"Retry-After\"\n }), \". This route ignores a leftover session cookie and does not apply the cookie origin guard.\"]\n });\n}\nfunction MDXContent(props = {}) {\n const {wrapper: MDXLayout} = {\n ..._provideComponents(),\n ...props.components\n };\n return MDXLayout ? _jsx(MDXLayout, {\n ...props,\n children: _jsx(_createMdxContent, {\n ...props\n })\n }) : _createMdxContent(props);\n}\nreturn {\n default: MDXContent\n};\n","frontmatter":{},"scope":{}},"pageType":"default","mdx":{"mdxSource":{"compiledSource":"\"use strict\";const{Fragment:_Fragment,jsx:_jsx}=arguments[0];const{useMDXComponents:_provideComponents}=arguments[0];function _createMdxContent(props){return _jsx(_Fragment,{})}function MDXContent(props={}){const{wrapper:MDXLayout}={..._provideComponents(),...props.components};return MDXLayout?_jsx(MDXLayout,{...props,children:_jsx(_createMdxContent,{...props})}):_createMdxContent(props)}return{default:MDXContent}","frontmatter":{},"scope":{"config":{},"pageMetadata":{"title":"Unlock a password-protected share","description":"No session. JSON `{ password }`. A matching password returns `{ grant: { token, expiresAt } }` valid for 15 minutes. A link with no password returns `{ grant: null }`. A wrong password is `401 PASSWORD_INCORRECT`. An inactive link is `404 ARTIFACT_NOT_FOUND`. A missing or non-JSON body is `400 INVALID_REQUEST` before any password throttle is charged. Client failures allow 10 per 10 minutes. Share failures allow 30 per 10 minutes, charged only after a wrong password. An exhausted share is `429 RATE_LIMITED` with `Retry-After` and no hash verification. A saturated Argon2 gate, or a share whose remaining slots are all in flight, is `503 UNLOCK_UNAVAILABLE` with `Retry-After`. This route ignores a leftover session cookie and does not apply the cookie origin guard.","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json post /api/v1/public/artifacts/{id}/{token}/unlock","href":"/api-reference/public/unlock-a-password-protected-share","autogeneratedByOpenApi":true}}},"mdxSourceWithNoJs":null},"mdxExtracts":{"tableOfContents":[],"codeExamples":{}},"jsLinks":[],"openApiReferenceData":{"operation":{"operationId":"unlockPublicArtifact","tags":["Public"],"summary":"Unlock a password-protected share","description":"No session. JSON `{ password }`. A matching password returns `{ grant: { token, expiresAt } }` valid for 15 minutes. A link with no password returns `{ grant: null }`. A wrong password is `401 PASSWORD_INCORRECT`. An inactive link is `404 ARTIFACT_NOT_FOUND`. A missing or non-JSON body is `400 INVALID_REQUEST` before any password throttle is charged. Client failures allow 10 per 10 minutes. Share failures allow 30 per 10 minutes, charged only after a wrong password. An exhausted share is `429 RATE_LIMITED` with `Retry-After` and no hash verification. A saturated Argon2 gate, or a share whose remaining slots are all in flight, is `503 UNLOCK_UNAVAILABLE` with `Retry-After`. This route ignores a leftover session cookie and does not apply the cookie origin guard.","security":[],"parameters":["87f3b8c1-e1f1-42c5-8f13-61d3b029a12b","801a5b7e-8773-4f26-a7ca-16e1f986fe98"],"requestBody":"27e1e068-262c-4d69-8702-0649d2dbe51c","responses":{"200":"82449a42-2750-4f47-8c41-5886e7f5551a","400":"eb91615d-0a57-47ef-b8a4-f763732ffc72","401":"0bd83547-0cb2-477e-973b-1f1428eb1e75","404":"f942adce-3842-4a6d-9e8b-70f60ee460fa","429":"31ac3b09-7098-4ca3-835c-b930dca38e85","503":"1adfe6f6-c3e4-4095-8f54-e68e8eff96ba"},"method":"post","type":"path","servers":["f7ed4e89-d556-412e-bb33-e97f0d376a70","36b86b74-9fdf-4f1e-a17c-f29f1f5c5c4d"],"path":"/api/v1/public/artifacts/{id}/{token}/unlock","baseUrlOptions":["http://localhost:3001","https://api.example.com"],"title":"Unlock a password-protected share","codeSamples":[],"requiredOnlyExamples":false,"disableCodeSampleGeneration":true,"responseExampleType":"generated"},"dependencies":{"parameters":{"87f3b8c1-e1f1-42c5-8f13-61d3b029a12b":{"name":"id","in":"path","required":true,"description":"Artifact UUID.","schema":{"type":"string","format":"uuid","pattern":"^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$","isRequired":true,"description":"Artifact UUID.","uniqueKey":"","typeLabel":"string\u003cuuid>"}},"801a5b7e-8773-4f26-a7ca-16e1f986fe98":{"name":"token","in":"path","required":true,"description":"Public share token from the owner share URL. The stored column is a hash, not this value.","schema":{"type":"string","minLength":1,"isRequired":true,"description":"Public share token from the owner share URL. The stored column is a hash, not this value.","uniqueKey":"","typeLabel":"string"}}},"requestBody":{"required":true,"description":"The link password.","content":{"application/json":{"schema":{"type":"object","properties":{"password":{"type":"string","minLength":1,"maxLength":1024,"isRequired":true,"uniqueKey":"password","typeLabel":"string"}},"required":["password"],"additionalProperties":false,"uniqueKey":"","typeLabel":"object"},"example":{"password":"example-link-password"},"examples":{"Example":{"title":"Example","value":{"password":"example-link-password"}}},"exampleType":"examples"}},"exampleType":"examples"},"responses":{"82449a42-2750-4f47-8c41-5886e7f5551a":{"description":"A grant for a protected link, or null when the link has no password.","content":{"application/json":{"schema":{"type":"object","properties":{"grant":{"oneOf":[{"type":"object","required":["token","expiresAt"],"properties":{"token":{"type":"string","minLength":1,"isRequired":true,"uniqueKey":"grant.oneOf.0.token","typeLabel":"string"},"expiresAt":{"type":"string","format":"date-time","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))T(?:(?:[01]\\d|2[0-3]):[0-5]\\d(?::[0-5]\\d(?:\\.\\d+)?)?(?:Z|([+-](?:[01]\\d|2[0-3]):[0-5]\\d)))$","isRequired":true,"uniqueKey":"grant.oneOf.0.expiresAt","typeLabel":"string\u003cdate-time>"}},"additionalProperties":false,"isRequired":true,"uniqueKey":"grant.oneOf.0","typeLabel":"object"},{"type":"null","isRequired":true,"uniqueKey":"grant.oneOf.1","typeLabel":"null"}],"isRequired":true,"uniqueKey":"grant","typeLabel":"object | null"}},"required":["grant"],"additionalProperties":false,"uniqueKey":"","typeLabel":"object"},"example":{"grant":{"token":"g1.example","expiresAt":"2026-10-21T12:15:00.000Z"}},"examples":{"Example":{"title":"Example","value":{"grant":{"token":"g1.example","expiresAt":"2026-10-21T12:15:00.000Z"}}}},"exampleType":"examples"}},"exampleType":"examples"},"eb91615d-0a57-47ef-b8a4-f763732ffc72":{"description":"Missing or non-JSON body. Code `INVALID_REQUEST`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"additionalProperties":false,"properties":{"code":{"type":"string","enum":["INVALID_REQUEST","ORGANIZATION_REQUIRED","ORGANIZATION_CHANGED","UNAUTHENTICATED","PASSWORD_REQUIRED","PASSWORD_INCORRECT","FORBIDDEN","ARTIFACT_NOT_FOUND","CONTENT_CONFLICT","FILE_TOO_LARGE","CONTENT_TOO_LARGE","UNSUPPORTED_FILE_TYPE","CONTENT_TOO_COMPLEX","RATE_LIMITED","INTERNAL_ERROR","STORAGE_UNAVAILABLE","CONVERSION_UNAVAILABLE","UNLOCK_UNAVAILABLE"],"description":"400/404 INVALID_REQUEST: The request is missing a required field, has the wrong shape, or failed validation. Typical causes are a missing file, an invalid access type, view, format, or artifact id, or invalid UTF-8. Unmatched non-public product routes also return 404 INVALID_REQUEST with message Not found. 400 ORGANIZATION_REQUIRED: The caller asked to share with an organization but has no current organization membership. Upload with accessType org_shared and PATCH /api/v1/artifacts/{id} for a private artifact both use this code. 409 ORGANIZATION_CHANGED: PATCH /api/v1/artifacts/{id} for a private artifact named an organizationId that is not the caller's current membership when the conditional UPDATE reads, or a deadlock, serialization failure, or lock timeout persisted after one retry. The artifact is not written. That UPDATE is the linearization point: an authorization change that commits after its snapshot can land before commit and does not cancel the share. About 16 seconds is the budget for the two attempts, not an endpoint deadline. An artifact that is already org_shared returns 200 instead. 401 UNAUTHENTICATED: The product route needs a session cookie or Authorization: Bearer API key, and neither was accepted. PATCH /api/v1/artifacts/{id} also returns this when the session was revoked or expired before the conditional update read it, and does not write. A revocation that commits after that snapshot does not cancel the share. 401 PASSWORD_REQUIRED: The public share is password protected and the request did not present a valid unlock grant or content ticket. 401 PASSWORD_INCORRECT: The password sent to the public unlock route did not match. 403 FORBIDDEN: A cookie-authenticated write used an Origin or Referer that is not WEB_ORIGIN or PUBLIC_BASE_URL. 404 ARTIFACT_NOT_FOUND: The artifact id is unknown, the caller cannot read it, or the public share token is not active. Rename and delete also use this body when the caller is not the creator, including an organization admin or another member who can read an org_shared artifact. Those cases share this body. 409 CONTENT_CONFLICT: Another replace of the same artifact revision finished first. Upload again to replace the current content. Delete returns this code when concurrent replaces prevent deletion after eight attempts. Retry DELETE. 413 FILE_TOO_LARGE: The upload is larger than the 10 MiB HTML limit. A JSON body larger than 102,400 bytes uses the same code with message The request is too large. 413 CONTENT_TOO_LARGE: Stored HTML is larger than the Markdown conversion input limit. 415 UNSUPPORTED_FILE_TYPE: The upload is not a .html or .htm file. 422 CONTENT_TOO_COMPLEX: Markdown conversion exceeded its time, memory, nesting, or output limit. 429 RATE_LIMITED: Too many public views from one client address, or too many password attempts. Password-attempt 429 responses include Retry-After. Public-view 429 responses do not. 500 INTERNAL_ERROR: An unexpected persistence or service failure. 503 STORAGE_UNAVAILABLE: Object storage failed. A failed upload leaves no artifact row. A failed artifact delete keeps the row. The object may already be gone, so retry DELETE. 503 CONVERSION_UNAVAILABLE: The Markdown conversion worker pool is full. This response does not include Retry-After. 503 UNLOCK_UNAVAILABLE: Password verification is busy because the process-wide Argon2 gate is saturated or every remaining share check slot is in flight. Includes Retry-After.","isRequired":true,"uniqueKey":"error.code","typeLabel":"enum\u003cstring>"},"message":{"type":"string","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"required":["error"],"additionalProperties":false,"description":"Product error envelope. Better Auth `/api/auth` routes may return a different JSON shape.","uniqueKey":"","typeLabel":"object"},"example":{"error":{"code":"INVALID_REQUEST","message":"Send the password as a string."}},"examples":{"Example":{"title":"Example","value":{"error":{"code":"INVALID_REQUEST","message":"Send the password as a string."}}}},"exampleType":"examples"}},"exampleType":"examples"},"0bd83547-0cb2-477e-973b-1f1428eb1e75":{"description":"Wrong password. Code `PASSWORD_INCORRECT`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"additionalProperties":false,"properties":{"code":{"type":"string","enum":["INVALID_REQUEST","ORGANIZATION_REQUIRED","ORGANIZATION_CHANGED","UNAUTHENTICATED","PASSWORD_REQUIRED","PASSWORD_INCORRECT","FORBIDDEN","ARTIFACT_NOT_FOUND","CONTENT_CONFLICT","FILE_TOO_LARGE","CONTENT_TOO_LARGE","UNSUPPORTED_FILE_TYPE","CONTENT_TOO_COMPLEX","RATE_LIMITED","INTERNAL_ERROR","STORAGE_UNAVAILABLE","CONVERSION_UNAVAILABLE","UNLOCK_UNAVAILABLE"],"description":"400/404 INVALID_REQUEST: The request is missing a required field, has the wrong shape, or failed validation. Typical causes are a missing file, an invalid access type, view, format, or artifact id, or invalid UTF-8. Unmatched non-public product routes also return 404 INVALID_REQUEST with message Not found. 400 ORGANIZATION_REQUIRED: The caller asked to share with an organization but has no current organization membership. Upload with accessType org_shared and PATCH /api/v1/artifacts/{id} for a private artifact both use this code. 409 ORGANIZATION_CHANGED: PATCH /api/v1/artifacts/{id} for a private artifact named an organizationId that is not the caller's current membership when the conditional UPDATE reads, or a deadlock, serialization failure, or lock timeout persisted after one retry. The artifact is not written. That UPDATE is the linearization point: an authorization change that commits after its snapshot can land before commit and does not cancel the share. About 16 seconds is the budget for the two attempts, not an endpoint deadline. An artifact that is already org_shared returns 200 instead. 401 UNAUTHENTICATED: The product route needs a session cookie or Authorization: Bearer API key, and neither was accepted. PATCH /api/v1/artifacts/{id} also returns this when the session was revoked or expired before the conditional update read it, and does not write. A revocation that commits after that snapshot does not cancel the share. 401 PASSWORD_REQUIRED: The public share is password protected and the request did not present a valid unlock grant or content ticket. 401 PASSWORD_INCORRECT: The password sent to the public unlock route did not match. 403 FORBIDDEN: A cookie-authenticated write used an Origin or Referer that is not WEB_ORIGIN or PUBLIC_BASE_URL. 404 ARTIFACT_NOT_FOUND: The artifact id is unknown, the caller cannot read it, or the public share token is not active. Rename and delete also use this body when the caller is not the creator, including an organization admin or another member who can read an org_shared artifact. Those cases share this body. 409 CONTENT_CONFLICT: Another replace of the same artifact revision finished first. Upload again to replace the current content. Delete returns this code when concurrent replaces prevent deletion after eight attempts. Retry DELETE. 413 FILE_TOO_LARGE: The upload is larger than the 10 MiB HTML limit. A JSON body larger than 102,400 bytes uses the same code with message The request is too large. 413 CONTENT_TOO_LARGE: Stored HTML is larger than the Markdown conversion input limit. 415 UNSUPPORTED_FILE_TYPE: The upload is not a .html or .htm file. 422 CONTENT_TOO_COMPLEX: Markdown conversion exceeded its time, memory, nesting, or output limit. 429 RATE_LIMITED: Too many public views from one client address, or too many password attempts. Password-attempt 429 responses include Retry-After. Public-view 429 responses do not. 500 INTERNAL_ERROR: An unexpected persistence or service failure. 503 STORAGE_UNAVAILABLE: Object storage failed. A failed upload leaves no artifact row. A failed artifact delete keeps the row. The object may already be gone, so retry DELETE. 503 CONVERSION_UNAVAILABLE: The Markdown conversion worker pool is full. This response does not include Retry-After. 503 UNLOCK_UNAVAILABLE: Password verification is busy because the process-wide Argon2 gate is saturated or every remaining share check slot is in flight. Includes Retry-After.","isRequired":true,"uniqueKey":"error.code","typeLabel":"enum\u003cstring>"},"message":{"type":"string","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"required":["error"],"additionalProperties":false,"description":"Product error envelope. Better Auth `/api/auth` routes may return a different JSON shape.","uniqueKey":"","typeLabel":"object"},"example":{"error":{"code":"PASSWORD_INCORRECT","message":"That password is not right."}},"examples":{"Example":{"title":"Example","value":{"error":{"code":"PASSWORD_INCORRECT","message":"That password is not right."}}}},"exampleType":"examples"}},"exampleType":"examples"},"f942adce-3842-4a6d-9e8b-70f60ee460fa":{"description":"The link is not active. Code `ARTIFACT_NOT_FOUND`.","content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"additionalProperties":false,"properties":{"code":{"type":"string","enum":["INVALID_REQUEST","ORGANIZATION_REQUIRED","ORGANIZATION_CHANGED","UNAUTHENTICATED","PASSWORD_REQUIRED","PASSWORD_INCORRECT","FORBIDDEN","ARTIFACT_NOT_FOUND","CONTENT_CONFLICT","FILE_TOO_LARGE","CONTENT_TOO_LARGE","UNSUPPORTED_FILE_TYPE","CONTENT_TOO_COMPLEX","RATE_LIMITED","INTERNAL_ERROR","STORAGE_UNAVAILABLE","CONVERSION_UNAVAILABLE","UNLOCK_UNAVAILABLE"],"description":"400/404 INVALID_REQUEST: The request is missing a required field, has the wrong shape, or failed validation. Typical causes are a missing file, an invalid access type, view, format, or artifact id, or invalid UTF-8. Unmatched non-public product routes also return 404 INVALID_REQUEST with message Not found. 400 ORGANIZATION_REQUIRED: The caller asked to share with an organization but has no current organization membership. Upload with accessType org_shared and PATCH /api/v1/artifacts/{id} for a private artifact both use this code. 409 ORGANIZATION_CHANGED: PATCH /api/v1/artifacts/{id} for a private artifact named an organizationId that is not the caller's current membership when the conditional UPDATE reads, or a deadlock, serialization failure, or lock timeout persisted after one retry. The artifact is not written. That UPDATE is the linearization point: an authorization change that commits after its snapshot can land before commit and does not cancel the share. About 16 seconds is the budget for the two attempts, not an endpoint deadline. An artifact that is already org_shared returns 200 instead. 401 UNAUTHENTICATED: The product route needs a session cookie or Authorization: Bearer API key, and neither was accepted. PATCH /api/v1/artifacts/{id} also returns this when the session was revoked or expired before the conditional update read it, and does not write. A revocation that commits after that snapshot does not cancel the share. 401 PASSWORD_REQUIRED: The public share is password protected and the request did not present a valid unlock grant or content ticket. 401 PASSWORD_INCORRECT: The password sent to the public unlock route did not match. 403 FORBIDDEN: A cookie-authenticated write used an Origin or Referer that is not WEB_ORIGIN or PUBLIC_BASE_URL. 404 ARTIFACT_NOT_FOUND: The artifact id is unknown, the caller cannot read it, or the public share token is not active. Rename and delete also use this body when the caller is not the creator, including an organization admin or another member who can read an org_shared artifact. Those cases share this body. 409 CONTENT_CONFLICT: Another replace of the same artifact revision finished first. Upload again to replace the current content. Delete returns this code when concurrent replaces prevent deletion after eight attempts. Retry DELETE. 413 FILE_TOO_LARGE: The upload is larger than the 10 MiB HTML limit. A JSON body larger than 102,400 bytes uses the same code with message The request is too large. 413 CONTENT_TOO_LARGE: Stored HTML is larger than the Markdown conversion input limit. 415 UNSUPPORTED_FILE_TYPE: The upload is not a .html or .htm file. 422 CONTENT_TOO_COMPLEX: Markdown conversion exceeded its time, memory, nesting, or output limit. 429 RATE_LIMITED: Too many public views from one client address, or too many password attempts. Password-attempt 429 responses include Retry-After. Public-view 429 responses do not. 500 INTERNAL_ERROR: An unexpected persistence or service failure. 503 STORAGE_UNAVAILABLE: Object storage failed. A failed upload leaves no artifact row. A failed artifact delete keeps the row. The object may already be gone, so retry DELETE. 503 CONVERSION_UNAVAILABLE: The Markdown conversion worker pool is full. This response does not include Retry-After. 503 UNLOCK_UNAVAILABLE: Password verification is busy because the process-wide Argon2 gate is saturated or every remaining share check slot is in flight. Includes Retry-After.","isRequired":true,"uniqueKey":"error.code","typeLabel":"enum\u003cstring>"},"message":{"type":"string","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"required":["error"],"additionalProperties":false,"description":"Product error envelope. Better Auth `/api/auth` routes may return a different JSON shape.","uniqueKey":"","typeLabel":"object"},"example":{"error":{"code":"ARTIFACT_NOT_FOUND","message":"Artifact was not found."}},"examples":{"Example":{"title":"Example","value":{"error":{"code":"ARTIFACT_NOT_FOUND","message":"Artifact was not found."}}}},"exampleType":"examples"}},"exampleType":"examples"},"31ac3b09-7098-4ca3-835c-b930dca38e85":{"description":"Too many password attempts for this client or this share. Code `RATE_LIMITED`. Every password-throttle 429 sends Retry-After. Counters are in memory on each API process.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. The API sets this when an `ApiErrorException` includes `retryAfterSeconds`: every password-throttle 429 RATE_LIMITED, and 503 UNLOCK_UNAVAILABLE. Public-view 429 and Markdown 503 CONVERSION_UNAVAILABLE do not set it.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"additionalProperties":false,"properties":{"code":{"type":"string","enum":["INVALID_REQUEST","ORGANIZATION_REQUIRED","ORGANIZATION_CHANGED","UNAUTHENTICATED","PASSWORD_REQUIRED","PASSWORD_INCORRECT","FORBIDDEN","ARTIFACT_NOT_FOUND","CONTENT_CONFLICT","FILE_TOO_LARGE","CONTENT_TOO_LARGE","UNSUPPORTED_FILE_TYPE","CONTENT_TOO_COMPLEX","RATE_LIMITED","INTERNAL_ERROR","STORAGE_UNAVAILABLE","CONVERSION_UNAVAILABLE","UNLOCK_UNAVAILABLE"],"description":"400/404 INVALID_REQUEST: The request is missing a required field, has the wrong shape, or failed validation. Typical causes are a missing file, an invalid access type, view, format, or artifact id, or invalid UTF-8. Unmatched non-public product routes also return 404 INVALID_REQUEST with message Not found. 400 ORGANIZATION_REQUIRED: The caller asked to share with an organization but has no current organization membership. Upload with accessType org_shared and PATCH /api/v1/artifacts/{id} for a private artifact both use this code. 409 ORGANIZATION_CHANGED: PATCH /api/v1/artifacts/{id} for a private artifact named an organizationId that is not the caller's current membership when the conditional UPDATE reads, or a deadlock, serialization failure, or lock timeout persisted after one retry. The artifact is not written. That UPDATE is the linearization point: an authorization change that commits after its snapshot can land before commit and does not cancel the share. About 16 seconds is the budget for the two attempts, not an endpoint deadline. An artifact that is already org_shared returns 200 instead. 401 UNAUTHENTICATED: The product route needs a session cookie or Authorization: Bearer API key, and neither was accepted. PATCH /api/v1/artifacts/{id} also returns this when the session was revoked or expired before the conditional update read it, and does not write. A revocation that commits after that snapshot does not cancel the share. 401 PASSWORD_REQUIRED: The public share is password protected and the request did not present a valid unlock grant or content ticket. 401 PASSWORD_INCORRECT: The password sent to the public unlock route did not match. 403 FORBIDDEN: A cookie-authenticated write used an Origin or Referer that is not WEB_ORIGIN or PUBLIC_BASE_URL. 404 ARTIFACT_NOT_FOUND: The artifact id is unknown, the caller cannot read it, or the public share token is not active. Rename and delete also use this body when the caller is not the creator, including an organization admin or another member who can read an org_shared artifact. Those cases share this body. 409 CONTENT_CONFLICT: Another replace of the same artifact revision finished first. Upload again to replace the current content. Delete returns this code when concurrent replaces prevent deletion after eight attempts. Retry DELETE. 413 FILE_TOO_LARGE: The upload is larger than the 10 MiB HTML limit. A JSON body larger than 102,400 bytes uses the same code with message The request is too large. 413 CONTENT_TOO_LARGE: Stored HTML is larger than the Markdown conversion input limit. 415 UNSUPPORTED_FILE_TYPE: The upload is not a .html or .htm file. 422 CONTENT_TOO_COMPLEX: Markdown conversion exceeded its time, memory, nesting, or output limit. 429 RATE_LIMITED: Too many public views from one client address, or too many password attempts. Password-attempt 429 responses include Retry-After. Public-view 429 responses do not. 500 INTERNAL_ERROR: An unexpected persistence or service failure. 503 STORAGE_UNAVAILABLE: Object storage failed. A failed upload leaves no artifact row. A failed artifact delete keeps the row. The object may already be gone, so retry DELETE. 503 CONVERSION_UNAVAILABLE: The Markdown conversion worker pool is full. This response does not include Retry-After. 503 UNLOCK_UNAVAILABLE: Password verification is busy because the process-wide Argon2 gate is saturated or every remaining share check slot is in flight. Includes Retry-After.","isRequired":true,"uniqueKey":"error.code","typeLabel":"enum\u003cstring>"},"message":{"type":"string","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"required":["error"],"additionalProperties":false,"description":"Product error envelope. Better Auth `/api/auth` routes may return a different JSON shape.","uniqueKey":"","typeLabel":"object"},"example":{"error":{"code":"RATE_LIMITED","message":"Too many password attempts. Try again later."}},"examples":{"Example":{"title":"Example","value":{"error":{"code":"RATE_LIMITED","message":"Too many password attempts. Try again later."}}}},"exampleType":"examples"}},"exampleType":"examples"},"1adfe6f6-c3e4-4095-8f54-e68e8eff96ba":{"description":"Password verification is busy. Code `UNLOCK_UNAVAILABLE`. Includes Retry-After.","headers":{"Retry-After":{"description":"Seconds to wait before retrying. The API sets this when an `ApiErrorException` includes `retryAfterSeconds`: every password-throttle 429 RATE_LIMITED, and 503 UNLOCK_UNAVAILABLE. Public-view 429 and Markdown 503 CONVERSION_UNAVAILABLE do not set it.","schema":{"type":"integer","minimum":1}}},"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"object","required":["code","message"],"additionalProperties":false,"properties":{"code":{"type":"string","enum":["INVALID_REQUEST","ORGANIZATION_REQUIRED","ORGANIZATION_CHANGED","UNAUTHENTICATED","PASSWORD_REQUIRED","PASSWORD_INCORRECT","FORBIDDEN","ARTIFACT_NOT_FOUND","CONTENT_CONFLICT","FILE_TOO_LARGE","CONTENT_TOO_LARGE","UNSUPPORTED_FILE_TYPE","CONTENT_TOO_COMPLEX","RATE_LIMITED","INTERNAL_ERROR","STORAGE_UNAVAILABLE","CONVERSION_UNAVAILABLE","UNLOCK_UNAVAILABLE"],"description":"400/404 INVALID_REQUEST: The request is missing a required field, has the wrong shape, or failed validation. Typical causes are a missing file, an invalid access type, view, format, or artifact id, or invalid UTF-8. Unmatched non-public product routes also return 404 INVALID_REQUEST with message Not found. 400 ORGANIZATION_REQUIRED: The caller asked to share with an organization but has no current organization membership. Upload with accessType org_shared and PATCH /api/v1/artifacts/{id} for a private artifact both use this code. 409 ORGANIZATION_CHANGED: PATCH /api/v1/artifacts/{id} for a private artifact named an organizationId that is not the caller's current membership when the conditional UPDATE reads, or a deadlock, serialization failure, or lock timeout persisted after one retry. The artifact is not written. That UPDATE is the linearization point: an authorization change that commits after its snapshot can land before commit and does not cancel the share. About 16 seconds is the budget for the two attempts, not an endpoint deadline. An artifact that is already org_shared returns 200 instead. 401 UNAUTHENTICATED: The product route needs a session cookie or Authorization: Bearer API key, and neither was accepted. PATCH /api/v1/artifacts/{id} also returns this when the session was revoked or expired before the conditional update read it, and does not write. A revocation that commits after that snapshot does not cancel the share. 401 PASSWORD_REQUIRED: The public share is password protected and the request did not present a valid unlock grant or content ticket. 401 PASSWORD_INCORRECT: The password sent to the public unlock route did not match. 403 FORBIDDEN: A cookie-authenticated write used an Origin or Referer that is not WEB_ORIGIN or PUBLIC_BASE_URL. 404 ARTIFACT_NOT_FOUND: The artifact id is unknown, the caller cannot read it, or the public share token is not active. Rename and delete also use this body when the caller is not the creator, including an organization admin or another member who can read an org_shared artifact. Those cases share this body. 409 CONTENT_CONFLICT: Another replace of the same artifact revision finished first. Upload again to replace the current content. Delete returns this code when concurrent replaces prevent deletion after eight attempts. Retry DELETE. 413 FILE_TOO_LARGE: The upload is larger than the 10 MiB HTML limit. A JSON body larger than 102,400 bytes uses the same code with message The request is too large. 413 CONTENT_TOO_LARGE: Stored HTML is larger than the Markdown conversion input limit. 415 UNSUPPORTED_FILE_TYPE: The upload is not a .html or .htm file. 422 CONTENT_TOO_COMPLEX: Markdown conversion exceeded its time, memory, nesting, or output limit. 429 RATE_LIMITED: Too many public views from one client address, or too many password attempts. Password-attempt 429 responses include Retry-After. Public-view 429 responses do not. 500 INTERNAL_ERROR: An unexpected persistence or service failure. 503 STORAGE_UNAVAILABLE: Object storage failed. A failed upload leaves no artifact row. A failed artifact delete keeps the row. The object may already be gone, so retry DELETE. 503 CONVERSION_UNAVAILABLE: The Markdown conversion worker pool is full. This response does not include Retry-After. 503 UNLOCK_UNAVAILABLE: Password verification is busy because the process-wide Argon2 gate is saturated or every remaining share check slot is in flight. Includes Retry-After.","isRequired":true,"uniqueKey":"error.code","typeLabel":"enum\u003cstring>"},"message":{"type":"string","isRequired":true,"uniqueKey":"error.message","typeLabel":"string"}},"isRequired":true,"uniqueKey":"error","typeLabel":"object"}},"required":["error"],"additionalProperties":false,"description":"Product error envelope. Better Auth `/api/auth` routes may return a different JSON shape.","uniqueKey":"","typeLabel":"object"},"example":{"error":{"code":"UNLOCK_UNAVAILABLE","message":"Password verification is busy. Try again."}},"examples":{"Example":{"title":"Example","value":{"error":{"code":"UNLOCK_UNAVAILABLE","message":"Password verification is busy. Try again."}}}},"exampleType":"examples"}},"exampleType":"examples"}},"security":{},"servers":{"f7ed4e89-d556-412e-bb33-e97f0d376a70":{"url":"http://localhost:3001","description":"Local development API origin"},"36b86b74-9fdf-4f1e-a17c-f29f1f5c5c4d":{"url":"https://api.example.com","description":"Example self-hosted API origin"}}},"originalFileLocation":"api-reference/openapi.json"},"subdomain":"factrove","siteName":"Factrove","title":"Unlock a password-protected share - Factrove","navMaps":{"firstHrefInVersion":{},"firstHrefInLanguage":{}},"lastModified":"2026-11-07T10:02:38.587Z","originalFileLocation":"api-reference/public/unlock-a-password-protected-share.mdx"},"headHtml":"\u003cscript data-mint-head>(function(){var d=document.documentElement,p=null;if(!p){try{p=localStorage.getItem(\"isDarkMode\")}catch(e){}if(p==='true')p='dark';else if(p==='false')p='light';if(p!=='light'\u0026\u0026p!=='dark'\u0026\u0026p!=='system')p=\"system\"}var r=p==='system'?(matchMedia(\"(prefers-color-scheme: dark)\").matches?'dark':'light'):p;d.classList.remove(r==='dark'?'light':'dark');d.classList.add(r);d.setAttribute(\"data-theme-preference\",p)})();\u003c/script>\u003cmeta data-mint-head name=\"description\" content=\"No session. JSON { password }. A matching password returns { grant: { token, expiresAt } } valid for 15 minutes. A link with no password returns { grant: null }. A wrong password is 401 PASSWORD_INCORRECT. An inactive link is 404 ARTIFACT_NOT_FOUND. A missing or non-JSON body is 400 INVALID_REQUEST before any password throttle is charged. Client failures allow 10 per 10 minutes. Share failures allow 30 per 10 minutes, charged only after a wrong password. An exhausted share is 429 RATE_LIMITED with Retry-After and no hash verification. A saturated Argon2 gate, or a share whose remaining slots are all in flight, is 503 UNLOCK_UNAVAILABLE with Retry-After. This route ignores a leftover session cookie and does not apply the cookie origin guard.\">\u003cmeta data-mint-head name=\"application-name\" content=\"Factrove\">\u003cmeta data-mint-head name=\"generator\" content=\"Mintlify\">\u003clink data-mint-head rel=\"apple-touch-icon\" type=\"image/png\" sizes=\"180x180\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/factrove/_generated/favicon/apple-touch-icon.png?v=3\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"32x32\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/factrove/_generated/favicon/favicon-32x32.png?v=3\">\u003clink data-mint-head rel=\"icon\" type=\"image/png\" sizes=\"16x16\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/factrove/_generated/favicon/favicon-16x16.png?v=3\">\u003clink data-mint-head rel=\"shortcut icon\" type=\"image/x-icon\" href=\"https://mintlify.s3.us-west-1.amazonaws.com/factrove/_generated/favicon/favicon.ico?v=3\">\u003cmeta data-mint-head property=\"og:title\" content=\"Unlock a password-protected share - Factrove\">\u003cmeta data-mint-head property=\"og:description\" content=\"No session. JSON { password }. A matching password returns { grant: { token, expiresAt } } valid for 15 minutes. A link with no password returns { grant: null }. A wrong password is 401 PASSWORD_INCORRECT. An inactive link is 404 ARTIFACT_NOT_FOUND. A missing or non-JSON body is 400 INVALID_REQUEST before any password throttle is charged. Client failures allow 10 per 10 minutes. Share failures allow 30 per 10 minutes, charged only after a wrong password. An exhausted share is 429 RATE_LIMITED with Retry-After and no hash verification. A saturated Argon2 gate, or a share whose remaining slots are all in flight, is 503 UNLOCK_UNAVAILABLE with Retry-After. This route ignores a leftover session cookie and does not apply the cookie origin guard.\">\u003cmeta data-mint-head property=\"og:site_name\" content=\"Factrove\">\u003cmeta data-mint-head property=\"og:url\" content=\"https://factrove.mintlify.app/api-reference/public/unlock-a-password-protected-share\">\u003cmeta data-mint-head property=\"og:type\" content=\"website\">\u003cmeta data-mint-head property=\"og:image\" content=\"https://factrove.mintlify.site/_mintlify/api/og/v2?division=Public\u0026amp;title=Unlock+a+password-protected+share\u0026amp;description=No+session.+JSON+%60%7B+password+%7D%60.+A+matching+password+returns+%60%7B+grant%3A+%7B+token%2C+expiresAt+%7D+%7D%60+valid+for+15+minutes.+A+link+with+no+password+returns+%60%7B+grant%3A+n\u0026amp;theme=ded3e32c59d8f988115330c3\u0026amp;signature=aad33486f9a50b870b75e1b23ddea45b64d55672877dd1ee80b242af9d695e63\">\u003cmeta data-mint-head property=\"og:image:width\" content=\"1200\">\u003cmeta data-mint-head property=\"og:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"twitter:card\" content=\"summary_large_image\">\u003cmeta data-mint-head name=\"twitter:title\" content=\"Unlock a password-protected share - Factrove\">\u003cmeta data-mint-head name=\"twitter:description\" content=\"No session. JSON { password }. A matching password returns { grant: { token, expiresAt } } valid for 15 minutes. A link with no password returns { grant: null }. A wrong password is 401 PASSWORD_INCORRECT. An inactive link is 404 ARTIFACT_NOT_FOUND. A missing or non-JSON body is 400 INVALID_REQUEST before any password throttle is charged. Client failures allow 10 per 10 minutes. Share failures allow 30 per 10 minutes, charged only after a wrong password. An exhausted share is 429 RATE_LIMITED with Retry-After and no hash verification. A saturated Argon2 gate, or a share whose remaining slots are all in flight, is 503 UNLOCK_UNAVAILABLE with Retry-After. This route ignores a leftover session cookie and does not apply the cookie origin guard.\">\u003cmeta data-mint-head name=\"twitter:image\" content=\"https://factrove.mintlify.site/_mintlify/api/og/v2?division=Public\u0026amp;title=Unlock+a+password-protected+share\u0026amp;description=No+session.+JSON+%60%7B+password+%7D%60.+A+matching+password+returns+%60%7B+grant%3A+%7B+token%2C+expiresAt+%7D+%7D%60+valid+for+15+minutes.+A+link+with+no+password+returns+%60%7B+grant%3A+n\u0026amp;theme=ded3e32c59d8f988115330c3\u0026amp;signature=aad33486f9a50b870b75e1b23ddea45b64d55672877dd1ee80b242af9d695e63\">\u003cmeta data-mint-head name=\"twitter:image:width\" content=\"1200\">\u003cmeta data-mint-head name=\"twitter:image:height\" content=\"630\">\u003cmeta data-mint-head name=\"msapplication-config\" content=\"https://mintlify.s3.us-west-1.amazonaws.com/factrove/_generated/favicon/browserconfig.xml?v=3\">\u003cmeta data-mint-head name=\"apple-mobile-web-app-title\" content=\"Factrove\">\u003cmeta data-mint-head name=\"msapplication-TileColor\" content=\"#5e64d6\">\u003clink data-mint-head rel=\"canonical\" href=\"https://factrove.mintlify.app/api-reference/public/unlock-a-password-protected-share\">\u003clink data-mint-head rel=\"alternate\" type=\"application/xml\" href=\"/sitemap.xml\">\u003clink data-mint-head rel=\"alternate\" type=\"text/markdown\" href=\"/api-reference/public/unlock-a-password-protected-share.md\">\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@graph\":[{\"@type\":\"Organization\",\"@id\":\"https://factrove.mintlify.app/#organization\",\"name\":\"Factrove\",\"url\":\"https://factrove.mintlify.app\"},{\"@type\":\"WebSite\",\"@id\":\"https://factrove.mintlify.app#website\",\"name\":\"Factrove\",\"url\":\"https://factrove.mintlify.app\",\"publisher\":{\"@id\":\"https://factrove.mintlify.app/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https://factrove.mintlify.app/api-reference/public/unlock-a-password-protected-share#webpage\",\"url\":\"https://factrove.mintlify.app/api-reference/public/unlock-a-password-protected-share\",\"name\":\"Unlock a password-protected share\",\"description\":\"No session. JSON { password }. A matching password returns { grant: { token, expiresAt } } valid for 15 minutes. A link with no password returns { grant: null }. A wrong password is 401 PASSWORD_INCORRECT. An inactive link is 404 ARTIFACT_NOT_FOUND. A missing or non-JSON body is 400 INVALID_REQUEST before any password throttle is charged. Client failures allow 10 per 10 minutes. Share failures allow 30 per 10 minutes, charged only after a wrong password. An exhausted share is 429 RATE_LIMITED with Retry-After and no hash verification. A saturated Argon2 gate, or a share whose remaining slots are all in flight, is 503 UNLOCK_UNAVAILABLE with Retry-After. This route ignores a leftover session cookie and does not apply the cookie origin guard.\",\"dateModified\":\"2026-11-07T10:02:38.587Z\",\"isPartOf\":{\"@id\":\"https://factrove.mintlify.app#website\"},\"breadcrumb\":{\"@id\":\"https://factrove.mintlify.app/api-reference/public/unlock-a-password-protected-share#breadcrumb\"}},{\"@type\":\"BreadcrumbList\",\"@id\":\"https://factrove.mintlify.app/api-reference/public/unlock-a-password-protected-share#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Public\",\"item\":\"https://factrove.mintlify.app/api-reference/public/read-a-public-share\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Unlock a password-protected share\",\"item\":\"https://factrove.mintlify.app/api-reference/public/unlock-a-password-protected-share\"}]},{\"@type\":[\"TechArticle\",\"APIReference\"],\"@id\":\"https://factrove.mintlify.app/api-reference/public/unlock-a-password-protected-share#apireference\",\"headline\":\"Unlock a password-protected share\",\"name\":\"Unlock a password-protected share\",\"description\":\"No session. JSON { password }. A matching password returns { grant: { token, expiresAt } } valid for 15 minutes. A link with no password returns { grant: null }. A wrong password is 401 PASSWORD_INCORRECT. An inactive link is 404 ARTIFACT_NOT_FOUND. A missing or non-JSON body is 400 INVALID_REQUEST before any password throttle is charged. Client failures allow 10 per 10 minutes. Share failures allow 30 per 10 minutes, charged only after a wrong password. An exhausted share is 429 RATE_LIMITED with Retry-After and no hash verification. A saturated Argon2 gate, or a share whose remaining slots are all in flight, is 503 UNLOCK_UNAVAILABLE with Retry-After. This route ignores a leftover session cookie and does not apply the cookie origin guard.\",\"url\":\"https://factrove.mintlify.app/api-reference/public/unlock-a-password-protected-share\",\"mainEntityOfPage\":{\"@id\":\"https://factrove.mintlify.app/api-reference/public/unlock-a-password-protected-share#webpage\"},\"dateModified\":\"2026-11-07T10:02:38.587Z\",\"publisher\":{\"@id\":\"https://factrove.mintlify.app/#organization\"},\"isPartOf\":{\"@id\":\"https://factrove.mintlify.app#website\"}}]}\u003c/script>\u003cscript data-mint-head type=\"application/ld+json\">{\"@context\":\"https://schema.org\",\"@type\":\"WebSite\",\"name\":\"Factrove\",\"creator\":{\"@type\":\"Organization\",\"name\":\"Mintlify\",\"url\":\"https://mintlify.com\"}}\u003c/script>","siteName":"Factrove","nav":{"global":null,"tabs":[{"tab":"Get started","pages":[{"title":"Get started","href":"/introduction"}]},{"tab":"Guides","pages":[{"title":"Guides","href":"/guides/self-hosting"}]},{"tab":"CLI reference","pages":[{"title":"CLI reference","href":"/cli-reference/overview"}]},{"tab":"API reference","groups":[{"group":"Overview","pages":[{"title":"API overview","href":"/api-reference/overview"}]},{"group":"Health","pages":[{"title":"Check that the API is initialized","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json get /api/v1/health","href":"/api-reference/health/check-that-the-api-is-initialized"}]},{"group":"Auth","pages":[{"title":"Return the caller and current organization","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json get /api/v1/context","href":"/api-reference/auth/return-the-caller-and-current-organization"},{"title":"Create an account with email and password","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json post /api/auth/sign-up/email","href":"/api-reference/auth/create-an-account-with-email-and-password"},{"title":"Sign in with email and password","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json post /api/auth/sign-in/email","href":"/api-reference/auth/sign-in-with-email-and-password"},{"title":"Create an API key","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json post /api/auth/api-key/create","href":"/api-reference/auth/create-an-api-key"},{"title":"List API keys for the session","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json get /api/auth/api-key/list","href":"/api-reference/auth/list-api-keys-for-the-session"},{"title":"Revoke an API key","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json post /api/auth/api-key/delete","href":"/api-reference/auth/revoke-an-api-key"}]},{"group":"Artifacts","pages":[{"title":"List artifacts for the caller","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json get /api/v1/artifacts","href":"/api-reference/artifacts/list-artifacts-for-the-caller"},{"title":"Upload an HTML file","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json post /api/v1/artifacts","href":"/api-reference/artifacts/upload-an-html-file"},{"title":"Download artifact HTML or converted Markdown","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json get /api/v1/artifacts/{id}/content","href":"/api-reference/artifacts/download-artifact-html-or-converted-markdown"},{"title":"Replace an artifact's stored HTML","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json put /api/v1/artifacts/{id}/content","href":"/api-reference/artifacts/replace-an-artifacts-stored-html"},{"title":"Get artifact metadata","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json get /api/v1/artifacts/{id}","href":"/api-reference/artifacts/get-artifact-metadata"},{"title":"Delete an artifact","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json delete /api/v1/artifacts/{id}","href":"/api-reference/artifacts/delete-an-artifact"},{"title":"Share a private artifact with the confirmed organization","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json patch /api/v1/artifacts/{id}","href":"/api-reference/artifacts/share-a-private-artifact-with-the-confirmed-organization"},{"title":"Rename an artifact","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json patch /api/v1/artifacts/{id}/name","href":"/api-reference/artifacts/rename-an-artifact"}]},{"group":"Shares","pages":[{"title":"Read the owner share state","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json get /api/v1/artifacts/{id}/share","href":"/api-reference/shares/read-the-owner-share-state"},{"title":"Create or update a public share","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json post /api/v1/artifacts/{id}/share","href":"/api-reference/shares/create-or-update-a-public-share"},{"title":"Revoke the public share","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json delete /api/v1/artifacts/{id}/share","href":"/api-reference/shares/revoke-the-public-share"},{"title":"Remove the password from a shared link","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json delete /api/v1/artifacts/{id}/share/password","href":"/api-reference/shares/remove-the-password-from-a-shared-link"}]},{"group":"Public","pages":[{"title":"Read a public share","description":"No session. The response omits creator, organization, access type, and the share URL. An inactive, unknown, or revoked token is `404 ARTIFACT_NOT_FOUND` and does not say whether the artifact exists. A password-protected share without a valid `X-Factrove-Share-Grant` is `401 PASSWORD_REQUIRED`. The view allowance is charged per visitor address before the link lookup and password check, so a 401 or 404 still consumes it. IPv6 addresses share a /64. A charge grants two companion content loads for 30 seconds. View units are limited to 60 per 60 seconds per client address, in memory on each API process. A content request without a remaining companion charges another view unit before its own lookup. That 429 does not include Retry-After. Responses send Referrer-Policy: no-referrer and X-Robots-Tag: noindex.","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json get /api/v1/public/artifacts/{id}/{token}","href":"/api-reference/public/read-a-public-share"},{"title":"Unlock a password-protected share","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json post /api/v1/public/artifacts/{id}/{token}/unlock","href":"/api-reference/public/unlock-a-password-protected-share"},{"title":"Download public share HTML","description":"No session. Markdown is not offered. A password-protected link needs a `ticket` query minted on a granted detail response. The ticket lasts 60 seconds and is honored at most 3 times per API process. Content on a protected link without a valid ticket is `401 PASSWORD_REQUIRED`. Reverse proxies should not log `?ticket=`.","deprecated":null,"version":null,"openapi":"/api-reference/openapi.json get /api/v1/public/artifacts/{id}/{token}/content","href":"/api-reference/public/download-public-share-html"}]}]}]},"basePath":"","title":"Unlock a password-protected share - Factrove","buildId":"dpl_FWZhTb2vab28gFGFH4ojka6qEznQ","deploymentId":"dpl_FWZhTb2vab28gFGFH4ojka6qEznQ","dynamics":["c2aa737661","2b790eda92","b0f84f53ff","a9bb46feb3"],"chunks":["OpenApiReferenceProvider-CBsVopKK.js","utils-DZAk68jJ.js","cloneDeep-izs3Hzxb.js","_Uint8Array-BVIqJ90l.js","isObjectLike-C8vmzPEN.js","isArray-Dcu1dQ5t.js","utils-D32AYZrP.js","toString-BX-iyh8G.js","isSymbol-CSH9U2Gm.js","addUniqueKeysToSchema-D_A5_cny.js","snippetPresets-xNRfS9th.js","style-to-object-BY3JEAdk.js","v4-DIgz8zy6.js","conditional-requirements-CFM0id0Q.js","ApiExamples-BIB25-tq.js","isEqual-BfaiBbcl.js","usePlaygroundInputsStore-CydJ4w4j.js","shallow-CYPBeQSG.js","getApiPlaygroundDisplay-A5xJVBOu.js","CodeSnippet-BVRTgi3m.js","CodeSnippets-DjD6BSlt.js","Page-Dr40SSJq.js","getPastedJson-D4V4JyrR.js","icon-uhcnG22T.js","MethodPill-CM-ZQdGH.js","DuplicateIcon-B_WnOiNf.js","createIcon-CJsb8utt.js","DynamicMarkdown-D-2HDKEp.js","SectionHeading-KP5xmMgQ.js","axios-vUo_bRtp.js","Markdown-D_k0dg6k.js","clsx-DK3K4Z1S.js","lib-DuNMoZ05.js","lib-B8HbPgcC.js","html-void-elements-mCSPHezU.js","dist-DE3EVdvd.js","katex-YMM-FMeD.js","marked.esm-CZWythHk.js","AssistantPageLink-fN9H9n9g.js"]}