Skip to content

External Approvers

External approvers are people outside your organisation — vendors, clients, contractors, counter-parties — who need to act on a workflow step but do not have an Aptiwise account.

They receive a one-time email link and can approve, reject, acknowledge, or sign directly from that link. No login, no account registration.


sequenceDiagram
participant R as Requestor
participant E as Aptiwise Engine
participant X as External Approver
R->>E: Submit workflow (includes vendor email)
E->>E: Create step, resolve approver email
E->>X: Send email with one-time link
X->>E: Open link → review request data
X->>E: Click Approve / Reject / Sign
E->>E: Complete step, advance workflow

The encrypted token in the email link encodes {instance_id, step_id, approver_email}. No session or login is required — the token is the sole auth mechanism.


Set employee_type: external on the approver block to mark the step as public-facing:

workflow:
vendor_review:
type: decision
approval_type: needs_to_approve # or needs_to_sign, needs_to_acknowledge
approver:
email: "vendor@example.com"
employee_type: external
on_approve:
end_workflow: true
on_reject:
end_workflow: true

All four approval types work for external approvers:

approval_type Effect
needs_to_approve External party approves or rejects
needs_to_sign External party draws and submits a signature
needs_to_acknowledge Non-blocking — external party acknowledges; workflow continues immediately
receives_a_copy Non-blocking — external party is notified; no action required

If the approver’s email is not known at design time, collect it in the form and reference it with ${form.<field_name>}:

form:
fields:
- name: vendor_name
type: text
label: Vendor Contact Name
required: true
- name: vendor_email
type: email
label: Vendor Email Address
required: true
help_text: "This person will receive a link to review and sign — no account needed"
workflow:
internal_approval:
type: decision
approval_type: needs_to_approve
approver:
role: "${requestor.manager}"
on_approve:
continue_to: vendor_sign
on_reject:
end_workflow: true
vendor_sign:
type: decision
approval_type: needs_to_sign
approver:
email: "${form.vendor_email}"
name: "${form.vendor_name}"
employee_type: external
on_approve:
end_workflow: true
on_reject:
end_workflow: true

The ${form.vendor_email} expression is resolved at step-creation time from the instance’s form data.

See docs/examples/external-approver-dynamic-email.yaml for a complete annotated example.


Every approver action — including public ones — is tied to an employees row for audit purposes. When an external approver opens their link, the system resolves their record in this order:

State What happens
Active employee with that email exists in the company Record reused — no duplicate created
Inactive employee with that email exists in the company Record reused — avoids a UNIQUE (email, company_id) constraint error
No record exists A minimal employee_type = external record is auto-created

This resolution is applied for all action types (approve, sign, acknowledge). You can safely use ${form.vendor_email} even if the vendor was previously registered or their account was deactivated.


POST /services/v1/approvals/public/{token}/action

Body:

{
"action": "approve",
"comments": "Reviewed and approved."
}

Works for all approval types. The token identifies the instance, step, and approver email.

External approvers who need to sign can draw their signature before or after acting:

GET /services/v1/signatures/public/{token} → check if a saved signature exists
POST /services/v1/signatures/public/{token} → save a drawn signature (base64 PNG)

See Signatures for the full signature canvas and field reference.


Auto-created records are minimal:

Field Value
name Derived from email (alice.smith@example.comAlice Smith)
employee_type external
is_active true
user_id null — no system account

Formally inviting the person later via the admin panel upgrades their record (adds user_id, full profile) without losing their approval history or saved signature.


See also: