Portfolios
Public portfolio pages, drafts, publishing, and analytics.
Description
Portfolios are published from a single PORTFOLIO-type Document to a
subdomain of veriworkly.com. The flow is: save a draft (PUT /portfolios/draft), preview it,
then publish it (POST /portfolios/publish) once the content passes the full validation schema.
Premium templates (nimbus, cipher) require an active Creator Pro subscription.
Publishing is temporarily admin-gated
In production, publishing currently requires the caller's email to match a hardcoded ADMIN_EMAIL
— independent of plan tier. Regular users can still save drafts, preview, and manage everything
except actually flipping a portfolio live. This is a rollout-phase restriction, not a permanent
limitation, and does not apply in development.
The /portfolios/public* routes serve published content and need no user session. View tracking is
buffered in Redis, deduplicated per viewer IP for 30 minutes, and flushed to Postgres by a
scheduled job — so POST /public/{subdomain}/view returns 202 and does not reflect a persisted
count.
Authentication
| Method | Access Level | Requirement |
|---|---|---|
/public, /public/{subdomain}, /public/{subdomain}/view | No session | An API key, or a whitelisted first-party origin. |
| All other routes | Authenticated | Session cookie only — no API key support. |
“Public” means no user session, not no credentials
The /portfolios/public* routes do not require a logged-in user, but they are not open to
anonymous callers. A request that carries neither an API key nor a whitelisted first-party
Origin/Referer is rejected with 401. Only GET /health and GET /health/ready are
genuinely unauthenticated.
Available Endpoints
GET /portfolios/public— List Public PortfoliosGET /portfolios/public/{subdomain}— Get Public Portfolio By SubdomainPOST /portfolios/public/{subdomain}/view— Record Portfolio ViewGET /portfolios/me— Get My PortfolioPUT /portfolios/draft— Save Portfolio DraftGET /portfolios/subdomains/{slug}/availability— Check Subdomain AvailabilityGET /portfolios/preview/{documentId}— Preview Portfolio DraftPOST /portfolios/publish— Publish PortfolioPOST /portfolios/unpublish— Unpublish PortfolioGET /portfolios/analytics— Get Portfolio Analytics
For uploading portfolio images, see Portfolio Assets.
Convert Resume Text To Structured JSONPOST
Uses AI to convert raw resume text into structured JSON Resume-shaped fields. Requires an active AI Credits or Bundle entitlement, and spends credits independently of the shared ATS scan quota above. Requires the `ai:write` API key scope when called with an API key.
List Public PortfoliosGET
Lists the subdomains of every portfolio currently in `LIVE` or `GRACE` status, most recently updated first. Returns subdomain and timestamp only — no portfolio content. No user session is required, but the request must carry an API key or originate from a whitelisted first-party origin; otherwise it is rejected with `401`. Cached for 5 minutes.