Pulp EngineDocument Rendering
Get started

Self-service report portal

Enable PORTAL_ENABLED=true and open /portal, which redirects to /editor/portal.html. The default is false; portal routes and the HTML entry return 404 portal_disabled. Administrators can prepare publication metadata while disabled.

Sign-in and permissions

Use a named personal key or the existing OIDC provider. Set OIDC_VIEWER_GROUPS to a comma-separated group list. Matching viewer groups take precedence over the editor wildcard; viewer SSO defaults to the portal unless an explicit relative return URL was supplied. OIDC persists email; administrators can set or clear it in Users or /admin/users/:id.

When enabled, the built-in viewer grants template:read and portal:run, subject to folder permissions. Raw rendering, template writes and schedule administration are denied. Roles with render:run or template:write can also run permitted publications. Custom roles can grant portal:run. Existing viewer raw-render permissions are preserved when the portal is disabled; legacy credential scopes are unchanged.

Personal runs, history and subscriptions require a named user. Shared keys can administer publications but do not identify an owner. Queries remain tenant-scoped and filter permission, publication and format availability before pagination.

Publish a report

In Labels > Portal, administrators choose an existing label (usually prod), category, summary, icon, formats and subscriptions. Publication is row metadata independent of version history. @latest is not a publication label.

PUT /templates/customer-summary/portal
Content-Type: application/json

{"enabled":true,"label":"prod","category":"Finance","summary":"Approved customer summary","icon":"file-text","formats":["pdf","docx"],"allowSubscriptions":true}

Icons: file-text, chart-column, table, receipt, briefcase, users. Formats are intersected with server capabilities; PPTX requires PPTX_ENABLED=true. Promoting the label changes subsequent runs; saving an unpromoted version does not.

Run and download

Choose a report, complete its guided form or typed parameters, select a format and run. The server resolves the publication label once and renders that exact version through the shared pipeline. A mapped report without typed parameters needs a custom input form.

Runs are archived with the user ID and source: portal. My runs lists only that user’s outputs. Signed downloads require the owning session and current report permission; a separate per-user signing namespace prevents reuse on the public archive route. Expiry, retention, revocation and download limits apply. The UI fetches with session headers before creating a local download.

Enable database document storage, blob storage and DOCUMENT_URL_SECRET. Runs cannot silently fall back to unretained outputs. Normal size, rate, usage and tenant-state controls apply.

Personal subscriptions

Subscribe me creates a durable schedule using static input, optional typed parameters and the publication label. PDF/DOCX are supported. Daily runs every day, weekly on Monday, monthly on the first, at the chosen time in its IANA timezone.

Delivery goes only to the user’s stored email; recipient overrides are rejected. Missing email returns 422 portal_email_missing. PORTAL_MAX_SUBSCRIPTIONS_PER_USER defaults to 10 and is enforced under a database advisory lock, including concurrent requests. Configure SMTP and SCHEDULE_ENABLED for delivery.

Before fetching data or rendering, each execution checks the portal flag, user, tenant, permission, publication, label, format and exact recipient. Revoked, unpublished or altered subscriptions stop. Email or publication-label changes require a new subscription; version promotion under the same label works. Users can remove their subscriptions after losing report permission.

API and SDKs

The Portal OpenAPI tag covers catalog/detail, run creation, own history, private downloads, own subscriptions and publication administration. Responses omit tenant IDs. Both SDKs expose client.portal; Python provides sync and async snake_case methods. Use a named editorToken session for personal operations.

const page = await client.portal.listReports({ category: 'Finance' })
const run = await client.portal.run(page.items[0].key, {
  format: 'pdf', data: { name: 'Ada' },
})
const link = new URL(run.downloadUrl!)
const bytes = await client.portal.downloadRun(run.runId, {
  exp: link.searchParams.get('exp')!, d: 'a', sig: link.searchParams.get('sig')!,
})

See guided interviews and deployment settings.