This guide connects PostHog to Candu so that anything PostHog knows about a user, such as person properties, cohort membership, or their latest activity, becomes a Candu trait you can use in segments and targeting.
No middleware and no code changes in your app. A PostHog workflow fires on an event and posts an identify call to Candu's REST API.
This is the companion to Send Candu data to PostHog, which covers the opposite direction. Together they form a full loop: Candu engagement data enriches PostHog, and PostHog-computed properties flow back to power Candu targeting.
What you get
Traits arrive on the user in Candu and update every time the workflow fires:
Candu trait | Example |
posthogLastEvent | signup_completed |
posthogPlan | enterprise (any PostHog person property) |
inPowerUsers | true (cohort membership, see below) |
[Screenshot: Candu user Traits tab showing arrived posthog traits]
Before you start: check your identity join
This is the one thing that will silently ruin the integration if you get it wrong.
The workflow sends PostHog's distinct_id as Candu's userId. If those two values are not the same string for the same human, traits will land on the wrong user or create a duplicate, and there is no error message when this happens.
Before building anything, confirm that the identifier you pass to posthog.identify() is the same userId you pass to Candu.
Step 1: Copy your Candu API key
In Candu, go to Settings > Workspaces > Access Keys and copy the API Key (not the Client Token). You will paste it into PostHog in Step 3.
Step 2: Create the PostHog workflow
In PostHog, go to Tools > Workflows, click New workflow and choose Empty workflow.
Click the Trigger node and set Trigger type to Event.
Choose the event that should update Candu. Any event works; pick something the user does regularly if you want traits to stay fresh.
Leave Frequency on Every time the trigger fires so traits keep updating.
Step 3: Add the Webhook action
From the Build panel, drag Webhook (under Dispatch) onto the line between Trigger and Exit. A drop zone appears on the line while you drag.
Fill in the node:
Webhook URL
https://api.candu.ai/api/eventWebhook
Method: POST
JSON Body
{
"type": "identify",
"userId": "{event.distinct_id}",
"traits": {
"posthogLastEvent": "{event.event}",
"posthogPlan": "{person.properties.plan}"
}
}
Headers
Content-Type | application/json |
Authorization | Bearer YOUR_CANDU_API_KEY |
Turn on Log responses. It shows you Candu's response code on every run, which makes the verify step below much easier.
Step 4: Map your traits
Values in curly braces are PostHog templating. Both the triggering event and the person are available:
Template | What it sends |
{event.distinct_id} | The user's ID. Use this as userId. |
{event.event} | The name of the triggering event |
{event.properties.plan} | Any property on the triggering event |
{person.properties.email} | Any person property PostHog holds |
"posthogPowerUser": true | Static values work too |
Templates must be quoted. "posthogPlan": {person.properties.plan} fails validation; "posthogPlan": "{person.properties.plan}" works.
Syncing cohort membership
There is no "entered cohort" trigger, but you can sync membership lazily: add a Cohort branch node between Trigger and Webhook, and on the branch for cohort members send a static trait such as "inPowerUsers": true. Membership then updates in Candu the next time each user fires the trigger event.
Step 5: Enable and verify
Click Save, then Enable the workflow.
Fire the trigger event as a test user.
Open the workflow's Invocations tab. You should see a SUCCEEDED run within a minute or two. With Log responses on, the expanded log shows the exact request sent to Candu and the response:
204means Candu accepted it.In Candu, go to Analytics > Users, open the user, and click the Traits tab. Your new traits will be there.
Troubleshooting
The workflow never fires
PostHog only runs workflows for users with a person profile. If you are testing with the capture API and a brand new distinct_id, include a $set property in the event, for example "$set": {"test": true}, so PostHog creates the person. Events from the PostHog SDK for identified users do not have this problem.
The invocation is delayed
Allow a minute or two between the event firing and the workflow running. This is normal PostHog ingestion time.
The run succeeds but no traits appear in Candu
Check that the userId Candu received matches an existing Candu user ID exactly. The expanded invocation log shows the resolved request body, so you can see exactly what was sent.
Candu returns 400
The identify call requires type, userId, and traits. Check the JSON body for typos, and note that a misspelled template such as {event.propertis.x} sends the literal text rather than failing.
Sending events instead of traits
The same webhook can send events rather than traits. Use this body instead:
{
"type": "track",
"userId": "{event.distinct_id}",
"event": "posthog_milestone_reached",
"properties": {
"source": "posthog-workflow"
}
}
Going the other way
Candu can also send its engagement data into PostHog, so content views, interactions, and form responses show up alongside the rest of your product analytics. See Send Candu data to PostHog.






