Skip to main content

POST /v1/public/pages/{slug}/unlock

Verifies the password for a gated page and returns a short-lived content token. The token is passed to the content-origin Worker (artifactausercontent.com/c/{slug}?token=...) to fetch the gated bytes. This endpoint is unauthenticated and is called by the Artifacta viewer after the visitor submits the password prompt. The token expires in 5 minutes (expires_in: 300). After expiry the viewer must call this endpoint again.

Authentication

None. This is a public endpoint.

Path parameters

ParameterTypeDescription
slugstringPage slug (pg_...) from the public URL.

Request body

{
  "password": "hunter2"
}
FieldTypeRequiredDescription
passwordstringYesThe passcode set when the page was published.

Response

{
  "content_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_in": 300
}
FieldTypeDescription
content_tokenstringSigned JWT (HS256). Carries slug, purpose: "page_content", and exp. Pass this as a query parameter to the content-origin Worker.
expires_inintegerToken lifetime in seconds. Always 300.

Error codes

CodeStatusWhen
artifact_not_found404Page is missing, unpublished, expired, or access is not "password". No oracle.
unauthorized401Password is incorrect. Same error code regardless of whether the slug exists (no oracle).
rate_limited429Too many unlock attempts for this slug. Try again after the Retry-After header value.
invalid_request400Missing or empty password field, or malformed JSON body.

Notes

  • Single failure mode: An incorrect password returns unauthorized, not artifact_not_found. However, a missing or unpublished slug also returns a non-200 status code — callers cannot distinguish wrong-password from missing-slug. This is intentional.
  • Brute-force protection: Attempts are rate-limited per slug plus a separate per-IP edge rule. The per-slug cap is the primary control.
  • Token scope: The token is single-purpose (purpose: "page_content") and accepted only by the content-origin Worker. It cannot be used to call any API endpoint.

Example

curl -X POST https://api.artifacta.io/v1/public/pages/pg_aB3xK9mP1qR5sT2u/unlock \
  -H "Content-Type: application/json" \
  -d '{"password": "hunter2"}'