Skip to content
ClientPress
  • Pricing
  • Features
  • Use CasesExpand
    • Coaches and Consultants
    • Employee Onboarding
    • Freelancers and Contractors
    • Teams Working With Outside Freelancers
    • Web and Digital Agencies
  • Contact
  • Log In
  • 0
ClientPress

Getting Started

7
  • Inviting a Client to Their Portal
  • Creating Your First Portal
  • User Roles Explained
  • Initial Setup Checklist
  • Plugin Overview — What ClientPress Does
  • Magic Login Links in Email Notifications
  • How to Link Clients to Their Portal

Navigation

1
  • How Client Login and Redirect Works

Assets, Files, and Deliverables

1
  • Portal Files — Browsing All Uploaded Files Across Portals

Client Setup

4
  • Onboarding — Guiding Clients Through Their First Steps
  • Managing Client Invitations
  • Assigning Project Managers to a Portal
  • Adding Sub-Clients to a Portal

Advanced

3
  • Uninstalling ClientPress — What Data Gets Deleted
  • Private File Storage and Security
  • Activity Log — What Gets Tracked and How to Use It

Automations and Integrations

5
  • REST API Overview
  • Connecting ClientPress to OttoKit
  • Connecting ClientPress to Make
  • Connecting ClientPress to Zapier
  • Using Webhooks with ClientPress

Features and Tabs

14
  • Onboarding — Guiding Clients Through Their First Steps
  • Docs — Adding Portal-Specific Client Documents
  • Guides — Creating and Assigning Global Support Docs
  • People Tab — Managing Portal Members
  • Tools & Links Tab — Building a Client Resource Board
  • Managing Deliverable Revisions
  • Deliverables — Sending Work for Client Approval
  • File Approval Workflow
  • Files Tab — Uploading and Managing Client Files
  • Calendar View — Visualizing Task Due Dates
  • Using the Kanban Board View for Tasks
  • Task Manager — Creating and Managing Tasks
  • Message Board — Topic-Based Team Discussions
  • Discussion Tab — Private Messaging with Clients

Notifications and Emails

3
  • Enabling or Disabling Admin Notifications
  • How Clients Can Manage Their Notification Preferences
  • How Portal Notifications Work

Portals and Hubs

6
  • Setting Portal Width and Layout per View
  • Configuring the Portal Landing Tab
  • Branding a Portal
  • Using Portal Templates
  • Managing Portal Status
  • Understanding Portals and Hubs (Child Portals)

Settings and Configuration

5
  • Setting Up the Login Redirect
  • Appearance Settings
  • Configuring Deliverable Categories and Revision Limits
  • Configuring File Upload Settings
  • Enabling and Disabling Portal Features Globally

Shortcodes and Theme

2
  • Customizing Portal Colors with the Theme Customizer
  • Shortcode Reference

Developer

5
  • ClientPress Hooks & Filters
  • ClientPress Outbound Webhooks
  • ClientPress Inbound Webhooks
  • ClientPress REST API
  • ClientPress Abilities API Integration
View Categories
  • Home
  • Support Documentation
  • Developer
  • ClientPress Outbound Webhooks

ClientPress Outbound Webhooks

9 min read

ClientPress can send a signed HTTP POST to any URL whenever a portal event occurs. Use this to connect your portals to Zapier, Make, n8n, OttoKit, or any custom HTTP endpoint — no vendor lock-in, no API polling required.


Configuration #

Go to Portals → Settings → Outbound Webhooks.

  • Webhook URL — The HTTPS endpoint that receives events. Leave blank to disable webhooks entirely.
  • Signing secret — Optional. When set, each request includes an X-CP-Signature header you can use to verify the payload came from your site.
  • Events to send — Checkboxes for each supported event. Only checked events trigger a delivery.

Request Format #

Every webhook is an HTTP POST with a JSON body and the following headers:

  • Content-Type — application/json
  • X-CP-Event — The event slug, e.g. task.completed
  • X-CP-Portal-ID — The portal post ID as a string
  • X-CP-Delivery — A UUID4 that uniquely identifies this delivery
  • User-Agent — ClientPress/{version}; https://clientpress.io
  • X-CP-Signature — sha256=<hmac> — only present when a signing secret is configured

Payload shape #

{
  "event":      "task.completed",
  "portal_id":  42,
  "portal_url": "https://your-site.com/client-portal/acme-corp/",
  "timestamp":  "2024-01-18T14:22:00+00:00",
  "data":       { ... event-specific fields ... }
}

timestamp is always UTC in ISO 8601 format (gmdate('c')).


Signature Verification #

When a signing secret is configured, ClientPress computes:

X-CP-Signature: sha256=<hex(HMAC-SHA256(raw_json_body, secret))>

To verify in PHP:

$expected = 'sha256=' . hash_hmac( 'sha256', file_get_contents('php://input'), YOUR_SECRET );
$received = $_SERVER['HTTP_X_CP_SIGNATURE'] ?? '';

if ( ! hash_equals( $expected, $received ) ) {
    http_response_code( 401 );
    exit;
}

To verify in Node.js:

const crypto = require('crypto');

function verify(body, secret, header) {
  const expected = 'sha256=' + crypto
    .createHmac('sha256', secret)
    .update(body, 'utf8')
    .digest('hex');
  return crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(header));
}

Always use a constant-time comparison (hash_equals / timingSafeEqual) to prevent timing attacks.


Event Catalog #

portal.created #

Fired when a portal is created via the REST API.

{
  "event": "portal.created",
  "portal_id": 58,
  "portal_url": "https://your-site.com/client-portal/riverside-dental/",
  "timestamp": "2024-02-01T09:15:22+00:00",
  "data": {
    "title":  "Riverside Dental",
    "slug":   "riverside-dental",
    "status": "pending"
  }
}

file.uploaded #

Fired when a file is uploaded to a portal.

{
  "event": "file.uploaded",
  "portal_id": 42,
  "portal_url": "https://your-site.com/client-portal/acme-corp/",
  "timestamp": "2024-01-10T09:00:00+00:00",
  "data": {
    "name":            "contract-q1-2024.pdf",
    "original":        "Contract Q1 2024.pdf",
    "size":            204800,
    "type":            "application/pdf",
    "approval_status": "none"
  }
}

approval_status is "pending" when the uploader required approval, "none" otherwise.


file.approved #

Fired when an admin or designated approver approves a file.

{
  "event": "file.approved",
  "portal_id": 42,
  "portal_url": "https://your-site.com/client-portal/acme-corp/",
  "timestamp": "2024-01-11T10:15:00+00:00",
  "data": {
    "name":     "contract-q1-2024.pdf",
    "original": "Contract Q1 2024.pdf"
  }
}

file.rejected #

Fired when a file is rejected.

{
  "event": "file.rejected",
  "portal_id": 42,
  "portal_url": "https://your-site.com/client-portal/acme-corp/",
  "timestamp": "2024-01-11T10:20:00+00:00",
  "data": {
    "name":           "contract-draft.docx",
    "original":       "Contract Draft.docx",
    "rejection_note": "Please use the updated template."
  }
}

rejection_note is null when no reason was given.


task.created #

Fired when a task is created in any portal task list.

{
  "event": "task.created",
  "portal_id": 42,
  "portal_url": "https://your-site.com/client-portal/acme-corp/",
  "timestamp": "2024-01-10T09:00:00+00:00",
  "data": {
    "id":           10,
    "title":        "Sign the contract",
    "list_id":      1,
    "due_date":     "2024-01-20",
    "assignee_ids": [7]
  }
}

due_date is null when no due date is set.


task.completed #

Fired when a task is marked complete. Does not fire on re-open.

{
  "event": "task.completed",
  "portal_id": 42,
  "portal_url": "https://your-site.com/client-portal/acme-corp/",
  "timestamp": "2024-01-18T14:22:00+00:00",
  "data": {
    "id":      10,
    "title":   "Sign the contract",
    "list_id": 1
  }
}

message.sent #

Fired when a message is posted in the portal’s 1-on-1 discussion thread.

{
  "event": "message.sent",
  "portal_id": 42,
  "portal_url": "https://your-site.com/client-portal/acme-corp/",
  "timestamp": "2024-01-17T11:05:00+00:00",
  "data": {
    "sender_id": 7
  }
}

invite.accepted #

Fired when a client follows their invitation link and creates their account.

{
  "event": "invite.accepted",
  "portal_id": 42,
  "portal_url": "https://your-site.com/client-portal/acme-corp/",
  "timestamp": "2024-01-12T08:30:00+00:00",
  "data": {
    "user_id":      7,
    "email":        "jane@acme.com",
    "display_name": "Jane Smith"
  }
}

board.topic_posted #

Fired when a new topic is created in the portal message board.

{
  "event": "board.topic_posted",
  "portal_id": 42,
  "portal_url": "https://your-site.com/client-portal/acme-corp/",
  "timestamp": "2024-01-15T10:00:00+00:00",
  "data": {
    "topic_id":  101,
    "title":     "Kickoff call notes",
    "author_id": 1
  }
}

deliverable.uploaded #

Fired when an admin or project manager uploads a new deliverable or adds a linked deliverable to a portal. Also fires when a revised version of an existing deliverable is uploaded.

{
  "event": "deliverable.uploaded",
  "portal_id": 42,
  "portal_url": "https://your-site.com/client-portal/acme-corp/",
  "timestamp": "2024-02-10T11:00:00+00:00",
  "data": {
    "id":          "del_66a1b2c3d4e5f",
    "name":        "logo-v2.pdf",
    "category":    "design",
    "type":        "application/pdf",
    "size":        204800,
    "linked":      false,
    "uploaded_by": 1
  }
}

linked is true when the deliverable is an external URL rather than an uploaded file; in that case type is "" and size is 0.

When approval is not required: If the deliverable was uploaded with the “Require client approval” toggle unchecked, it is immediately approved at upload time. This event fires with the deliverable already in that state — deliverable.in_review and deliverable.approved will never fire for it.


deliverable.in_review #

Fired when an admin or project manager marks a deliverable as ready for client review.

{
  "event": "deliverable.in_review",
  "portal_id": 42,
  "portal_url": "https://your-site.com/client-portal/acme-corp/",
  "timestamp": "2024-02-10T14:30:00+00:00",
  "data": {
    "id":       "del_66a1b2c3d4e5f",
    "name":     "logo-v2.pdf",
    "category": "design"
  }
}

deliverable.approved #

Fired when a client approves a deliverable.

{
  "event": "deliverable.approved",
  "portal_id": 42,
  "portal_url": "https://your-site.com/client-portal/acme-corp/",
  "timestamp": "2024-02-11T09:15:00+00:00",
  "data": {
    "id":          "del_66a1b2c3d4e5f",
    "name":        "logo-v2.pdf",
    "category":    "design",
    "approved_by": 7,
    "approved_at": "2024-02-11 09:15:00"
  }
}

deliverable.revision_requested #

Fired when a client requests revisions on a deliverable. Use this to notify your team in Slack, create a task in your project management tool, or trigger an internal workflow.

{
  "event": "deliverable.revision_requested",
  "portal_id": 42,
  "portal_url": "https://your-site.com/client-portal/acme-corp/",
  "timestamp": "2024-02-10T16:45:00+00:00",
  "data": {
    "id":                "del_66a1b2c3d4e5f",
    "name":              "logo-v2.pdf",
    "category":          "design",
    "revision_note":     "Please try a darker shade of blue.",
    "revisions_used":    1,
    "revisions_allowed": 3
  }
}

revision_note is "" when the client did not add a note. revisions_used and revisions_allowed are both 0 when the revisions system is disabled in Settings.


Delivery Behaviour #

  • Fire-and-forget — WordPress sends the request with blocking: false. ClientPress does not wait for a response. This means webhooks never add latency to the portal action that triggered them.
  • No retries — If your endpoint is down or returns an error, the payload is silently dropped. Build your endpoint to respond quickly (under 5 seconds) and implement idempotency using the X-CP-Delivery UUID if needed.
  • SSL — TLS verification is enabled by default. To disable it (e.g. for local development), add this to your theme’s functions.php:
    add_filter( 'cp_webhook_sslverify', '__return_false' );
    

Zapier / Make / n8n Quick-Start #

Zapier #

  1. Create a new Zap → trigger Webhooks by Zapier → Catch Hook.
  2. Copy the webhook URL Zapier gives you.
  3. Paste it into Portals → Settings → Webhook URL.
  4. Check the events you want to forward.
  5. Send a test event (e.g. complete a task) to capture a sample payload.
  6. Map the payload fields to your Zap actions.

Make (formerly Integromat) #

  1. Create a scenario → add a Webhooks → Custom webhook module.
  2. Copy the webhook URL and paste it into ClientPress Settings.
  3. Trigger a test event to let Make detect the payload structure automatically.
  4. Connect subsequent modules using the mapped fields.

n8n #

  1. Add a Webhook node (POST method).
  2. Copy the production URL and paste it into ClientPress Settings.
  3. Execute the workflow once manually to capture a test payload.
  4. Wire the output to whatever downstream nodes you need.

Extending #

To dispatch a webhook from custom code (e.g. a third-party plugin integration):

\CP\Webhooks::dispatch( 'task.completed', $portal_id, [
    'id'      => $task_id,
    'title'   => $task_title,
    'list_id' => $list_id,
] );

Only events listed in Webhooks::EVENTS and enabled in Settings will actually fire — unrecognised slugs are silently ignored.

Updated on June 9, 2026

What are your Feelings

  • Happy
  • Normal
  • Sad

Share This Article :

  • Facebook
  • X
  • LinkedIn
  • Pinterest
ClientPress Hooks & FiltersClientPress Inbound Webhooks

Leave a ReplyCancel reply

Table of Contents
  • Configuration
  • Request Format
    • Payload shape
  • Signature Verification
  • Event Catalog
    • portal.created
    • file.uploaded
    • file.approved
    • file.rejected
    • task.created
    • task.completed
    • message.sent
    • invite.accepted
    • board.topic_posted
    • deliverable.uploaded
    • deliverable.in_review
    • deliverable.approved
    • deliverable.revision_requested
  • Delivery Behaviour
  • Zapier / Make / n8n Quick-Start
    • Zapier
    • Make (formerly Integromat)
    • n8n
  • Extending

Use Cases

  • Coaches and Consultants
  • Employee Onboarding
  • Freelancers and Independent Contractors
  • Teams Working With Outside Freelancers
  • Web and Digital Agencies

How We Compare

  • Market Comparison
  • ClientPress vs Client Portal
  • ClientPress vs. Asana
  • ClientPress vs. Basecamp
  • ClientPress vs. Microsft Teams
  • Clientpress vs. Clickup

Customers

  • Dashboard

Support

  • Documentation
  • Support
  • Changelog
  • Roadmap

Affiliates

  • Affiliate Program
  • Affiliate Dashboard
  • Affiliate Terms and Conditions

Legal

  • Privacy Policy
  • Terms of Service

© 2026 ClientPress

Review My Order

0

Subtotal

Taxes & shipping calculated at checkout

Checkout
  • Pricing
  • Features
  • Use Cases
    • Coaches and Consultants
    • Employee Onboarding
    • Freelancers and Contractors
    • Teams Working With Outside Freelancers
    • Web and Digital Agencies
  • Contact
  • Log In
  • 0

Notifications