Identified Accounts Webhook¶
Send every company Rose identifies visiting your site to your own endpoint — the moment it's identified. Wire those accounts straight into your CRM, n8n, Zapier, or any HTTPS endpoint and build your own follow-up: alert a rep, create a lead, enrich further, or drop a row in your warehouse.
This is self-serve — you set it up yourself on the Integrations page, no account manager needed.
How it works¶
When Rose identifies a company behind a visit (via IP / company enrichment),
it sends a single POST to your webhook URL with that account's details as
JSON. One request per newly identified account — Rose de-duplicates upstream, so
a returning visitor already identified doesn't fire again.
Delivery is best-effort and fully in the background: if your endpoint is slow or down, your visitors' experience is never affected. Rose retries a few times (with backoff) and then gives up for that account.
De-duplication is best-effort, so on rare occasions the same account can arrive
twice. Every payload carries a stable event_id — de-duplicate on it and ignore
any repeat you've already processed.
What you need¶
- An HTTPS endpoint that accepts a
POSTwith a JSON body (a Zapier "Catch Hook", an n8n Webhook node, or your own API route). - Access to the Rose backoffice Integrations page for your site.
Set it up¶
- In the Rose backoffice, open Integrations and find the Identified accounts webhook card (under Webhooks).
- Turn Enable webhook on, then click Configure and fill in:
| Setting | What to enter |
|---|---|
| Webhook URL | The HTTPS address that receives each identified account. Example: https://hooks.zapier.com/hooks/catch/123/abc. |
| Secret key (optional) | A secret you choose so your endpoint can confirm the request really came from Rose. Leave empty to skip. See Verifying the signature. |
- Click Save. The next company identified on your site is posted to your endpoint.
The payload¶
Rose sends a JSON body like this:
{
"event_type": "account_identified",
"event_id": "9f2c1a...e3b7",
"timestamp": "2026-07-06T14:32:10.123456+00:00",
"site_name": "yourdomain.com",
"person_id": "0191f2a4-...",
"account": {
"company_name": "Acme Inc",
"domain": "acme.com",
"company_description": "B2B logistics software",
"sector": "Software",
"sub_sector": "Supply chain",
"company_linkedin_url": "https://www.linkedin.com/company/acme",
"location": "Boston, MA",
"employee_count": "51-200",
"country": "US"
},
"person": {
"job_title": "VP Sales",
"linkedin_url": "https://www.linkedin.com/in/jane-doe",
"email": "jane@acme.com"
},
"enrichment": {
"source": "enrich_so",
"tier": "enrich_so_api",
"enriched_at": "2026-07-06T14:32:10+00:00"
}
}
| Field | Description |
|---|---|
event_type |
Always account_identified. |
event_id |
Stable id for one identified account. Use it to de-duplicate: if you receive two requests with the same event_id, treat them as the same account and ignore the repeat. |
timestamp |
When Rose sent the webhook (ISO 8601, UTC). |
site_name |
Your site domain. |
person_id |
Rose's anonymous visitor id, when known (may be null). |
account |
The identified company. Any field Rose couldn't determine is null. |
person |
Person-level details when the source provides them (often null for company-only identification). |
enrichment |
Which source identified the account and when. |
Some fields depend on what the enrichment source returns — expect
nullfor anything unavailable for a given account. Always code your endpoint to tolerate missing fields.
Verifying the signature¶
If you set a Secret key, Rose adds an X-Webhook-Signature header to every
request: a hex-encoded HMAC-SHA256 of the raw request body, keyed with your
secret. Recompute it on your side and compare to confirm the request is genuine.
Node.js example:
const crypto = require('crypto');
function isFromRose(rawBody, signatureHeader, secret) {
const expected = crypto
.createHmac('sha256', secret)
.update(rawBody) // the exact raw bytes, before JSON parsing
.digest('hex');
return crypto.timingSafeEqual(
Buffer.from(expected),
Buffer.from(signatureHeader)
);
}
Sign over the raw body bytes exactly as received — parsing and re-serializing the JSON can change the bytes and break the check.
Troubleshooting¶
| Nothing arrives at your endpoint | Likely cause / fix |
|---|---|
| No requests at all | Check Enable webhook is on and Save was clicked, and that the Webhook URL starts with https://. |
| Requests but company data looks empty | Rose only fires once a company is actually identified. Fields the source couldn't resolve come through as null. |
| Signature never matches | Recompute HMAC over the raw body, not the re-serialized JSON, and confirm the secret matches exactly. |
| A known visitor didn't fire | Rose de-duplicates already-identified accounts — a returning identified visitor won't re-fire. |