Widget Guide

Embeddable Approval Widget

Embed a fully functional draft review and approval interface directly into your application using an iframe or the widget API.

Overview

The processa embeddable widget lets your team review and approve AI-generated drafts without leaving your application. The widget is a self-contained UI that communicates with the processa API using a publishable key (prefixed with pk_).

Key capabilities:

  • Display draft title, content preview, and current status
  • Approve or reject drafts with optional reviewer name and rejection reason
  • Real-time status polling with ETag-based caching
  • Light and dark theme support
  • Fully responsive and self-contained

Quick Start

1. Generate a Publishable Key

Navigate to Dashboard → API Keys and generate a new publishable key. Publishable keys are prefixed with pk_ and are safe to use in client-side code. They can only access the embed endpoints.

2. Configure Allowed Origins

For security, add your application's domain to the allowed origins list in Dashboard → Settings. This ensures the widget can only be embedded on authorized domains.

3. Embed the Widget

Add the iframe embed code to your application, replacing the draft ID and publishable key with your own values:

<iframe
  src="https://app.getprocessa.com/embed/drafts/DRAFT_ID?key=pk_YOUR_KEY&theme=light"
  width="100%"
  height="400"
  frameborder="0"
  style="border: none; border-radius: 12px;"
></iframe>

iframe Embed

The simplest way to embed the widget is using an iframe. The widget URL follows this pattern:

https://app.getprocessa.com/embed/drafts/{draftId}?key={publishableKey}&theme={light|dark}

Query Parameters

key
Required. Your publishable key (pk_...). Used to authenticate embed API requests.
theme
Optional. Either light or dark. Defaults to light.

React Example

function ApprovalEmbed({ draftId }: { draftId: string }) {
  const publishableKey = process.env.NEXT_PUBLIC_PROCESSA_PK

  return (
    <iframe
      src={`https://app.getprocessa.com/embed/drafts/${draftId}?key=${publishableKey}&theme=dark`}
      width="100%"
      height="400"
      style={{ border: 'none', borderRadius: '12px' }}
      title="Draft Approval"
    />
  )
}

HTML Example

<!-- Embed in any HTML page -->
<div style="max-width: 500px; margin: 0 auto;">
  <iframe
    id="getprocessa-widget"
    src="https://app.getprocessa.com/embed/drafts/YOUR_DRAFT_ID?key=pk_YOUR_KEY&theme=light"
    width="100%"
    height="400"
    frameborder="0"
    style="border: none; border-radius: 12px; box-shadow: 0 1px 3px rgba(0,0,0,0.1);"
  ></iframe>
</div>

Embed API Endpoints

If you prefer to build your own UI, you can use the embed API endpoints directly. All endpoints require a publishable key in the Authorization header.

GET/api/v1/embed/drafts/:id

Fetch a single draft by ID. Returns the draft title, content, status, and timestamps.

Request

GET /api/v1/embed/drafts/cmlgx2hvq0002k6gve9fuaz0k
Authorization: Bearer pk_your_publishable_key

Response

{
  "id": "cmlgx2hvq0002k6gve9fuaz0k",
  "title": "Send welcome email",
  "content": { "to": "user@example.com", "subject": "Welcome!" },
  "status": "PENDING",
  "metadata": {},
  "createdAt": "2026-02-10T12:00:00Z",
  "updatedAt": "2026-02-10T12:00:00Z",
  "expiresAt": null
}
POST/api/v1/embed/drafts/:id/approve

Approve a pending draft. Optionally include a reviewer name.

Request Body

{
  "reviewerName": "Alice Smith"  // optional
}

Response

{
  "id": "cmlgx2hvq0002k6gve9fuaz0k",
  "status": "APPROVED",
  "reviewedAt": "2026-02-10T12:05:00Z"
}
POST/api/v1/embed/drafts/:id/reject

Reject a pending draft. Optionally include a rejection reason and reviewer name.

Request Body

{
  "rejectionReason": "Content needs revision",  // optional
  "reviewerName": "Bob Jones"                    // optional
}

Response

{
  "id": "cmlgx2hvq0002k6gve9fuaz0k",
  "status": "REJECTED",
  "rejectionReason": "Content needs revision",
  "reviewedAt": "2026-02-10T12:05:00Z"
}
GET/api/v1/embed/drafts/:id/status

Poll the current status of a draft. Supports ETag-based conditional requests for efficient polling. Returns 304 Not Modified if the status has not changed.

Request

GET /api/v1/embed/drafts/cmlgx2hvq0002k6gve9fuaz0k/status
Authorization: Bearer pk_your_publishable_key
If-None-Match: "etag_value_from_previous_response"

Response

{
  "status": "PENDING",
  "reviewedAt": null,
  "rejectionReason": null
}

Security

Publishable Keys

Publishable keys (pk_) are designed to be used in client-side code. They have restricted permissions and can only access the embed API endpoints. They cannot create drafts, manage webhooks, or access other API resources.

Important: Never expose your secret API key (hal_) in client-side code. Always use publishable keys for the embed widget.

CORS & Origin Allowlist

Embed API endpoints enforce CORS restrictions. Only requests from domains listed in your allowed origins configuration will be accepted. Configure allowed origins in your account settings.

iframe Sandboxing

The embed page runs in a minimal layout with no navigation or session context. It only communicates via the embed API endpoints using the publishable key provided in the URL query parameter. No cookies or session tokens are used.

Theming

The widget supports light and dark themes. Pass the theme query parameter to match your application's appearance.

Light Theme

?theme=light

Clean, bright interface ideal for light-mode applications.

Dark Theme

?theme=dark

Dark interface that blends with dark-mode applications.
<!-- Light theme (default) -->
<iframe src="https://app.getprocessa.com/embed/drafts/ID?key=pk_KEY&theme=light" ...></iframe>

<!-- Dark theme -->
<iframe src="https://app.getprocessa.com/embed/drafts/ID?key=pk_KEY&theme=dark" ...></iframe>