Send RecordJoy Video Events to HubSpot with n8n
When you finish this guide, every RecordJoy event will upsert a HubSpot contact and log a note on their timeline, via an n8n workflow you own.
flowchart LR A[RecordJoy] -->|"event JSON"| B["n8n Webhook node"] B --> C["HubSpot: upsert contact"] C --> D["HubSpot: create note"] D --> E[(HubSpot)]
Shortcut: RecordJoy ships an importable version of this workflow —
docs/recipes/n8n-hubspot.jsonin the repository. The steps below build the same thing by hand.
Prerequisites
- An n8n instance reachable over HTTPS (Cloud or self-hosted)
- A HubSpot Private App token: in HubSpot, Settings → Integrations →
Private Apps → Create app, grant scopes
crm.objects.contacts.write,crm.objects.contacts.read, andcrm.objects.notes.write, then copy the token (startspat-) - RecordJoy account (any plan)
Estimated time
25 minutes
Steps
Part A — the webhook
- In n8n, click + Add workflow and name it
RecordJoy → HubSpot. - Add a Webhook node: HTTP Method
POST, Pathrecordjoy-hubspot. - Click Save, then switch the Active toggle on.
- Open the Webhook node and copy the Production URL.
<!-- SCREENSHOT: n8n-workflow-active-production-url.png -->🖥️ What you should see: a URL like
https://your-instance.app.n8n.cloud/webhook/recordjoy-hubspot.
- In
recordjoy.ai→ dashboard sidebar → CRM Integration: paste the URL, tick your events, click Save, then Send test event. - In n8n's Executions tab, confirm an execution arrived with
"event": "recording.test"underbody.
Part B — upsert the contact
- Add an HTTP Request node connected to the Webhook node; name it
Upsert Contact. - Configure:
- Method:
POST - URL:
https://api.hubapi.com/crm/v3/objects/contacts/batch/upsert - Authentication:
Generic Credential Type→Header Auth— create a credential with NameAuthorizationand ValueBearer pat-XXXX(your Private App token) - Body Content Type:
JSON, Specify Body:Using JSON
- Method:
- Paste this as the JSON body:
={{ { "inputs": [ { "idProperty": "email", "id": $json.body.recording.sentTo || $json.body.recording.createdBy, "properties": { "email": $json.body.recording.sentTo || $json.body.recording.createdBy } } ] } }}
Contact rule: this maps
sentTowith acreatedByfallback. For inboundrecording.receivedevents usesentByinstead — simplest is a separate workflow per rule.
- Click Execute step (with a pinned test execution) and confirm the
output contains
results[0].id.
<!-- SCREENSHOT: n8n-hubspot-upsert-output.png -->🖥️ What you should see: a JSON response with
status: COMPLETEand a numeric contact id underresults[0].id.
Part C — create the note
- Add another HTTP Request node connected to
Upsert Contact; name itCreate Note. Use the same Header Auth credential. - Configure: Method
POST, URLhttps://api.hubapi.com/crm/v3/objects/notes, BodyJSON:
={{ { "properties": { "hs_note_body": "RecordJoy " + $('Webhook').item.json.body.event + " — " + ($('Webhook').item.json.body.recording.description || "") + " — watch: " + $('Webhook').item.json.body.recording.viewUrl + " (watched " + ($('Webhook').item.json.body.recording.watchedTimes || 0) + "x)", "hs_timestamp": Date.now() }, "associations": [ { "to": { "id": $json.results[0].id }, "types": [ { "associationCategory": "HUBSPOT_DEFINED", "associationTypeId": 202 } ] } ] } }}
- Click Save and confirm the workflow is still Active.
Verification
- In RecordJoy → CRM Integration, click Send test event.
- In n8n Executions, confirm a green (successful) run through all three nodes.
- In HubSpot, open the contact matching your account email.
<!-- SCREENSHOT: hubspot-note-on-timeline.png -->🖥️ What you should see: a Note on the timeline containing
recording.testand arecordjoy.ai/view/...link.
Troubleshooting
| Problem | Fix |
|---|---|
| 401 from HubSpot | The Header Auth value must be Bearer pat-XXX (with the word Bearer and a space). Check the Private App token and scopes. |
results[0].id is undefined in the note step | The upsert failed or the expression references the wrong node. The note's association id must read from the Upsert Contact node's output. |
| Execution succeeds but no note in HubSpot | Wrong association type. Confirm associationTypeId: 202 (note→contact) and that the contact id is numeric. |
Ready to connect?
Your webhook settings live in Dashboard → CRM Integration.