Skip to content

02 Get your data in /Integrations

n8n

Send records from any of n8n's apps to Dimension Labs with a workflow and the universal API, on n8n Cloud or your own n8n.

  1. N n8nTickets, chats, calls, reviews
  2. ⟳ Your jobPull new · map fields · every 15 min
  3. { } Universal APIPOST /track · /trackhistorical
  4. Dimension LabsRead in full · enriched daily

n8n connects to thousands of apps (n8n’s integrations page lists 2,000+ as of 2026-10-26). If a tool you use has an n8n trigger, such as a new form response, review, ticket or spreadsheet row, a workflow can send each new record to the universal API. It runs on n8n Cloud or on your own n8n, with nothing else to host.

n8n fits sources where one trigger event is one piece of customer text: a form or survey response, a review, a feedback submission, the first message of a ticket. For full multi-message conversations, or to load history, use the app’s own guide or Any other system, which pull every message in order.

  • An n8n Cloud account or a self-hosted n8n.
  • An n8n trigger for your app that returns the customer’s text and a date.
  • A Dimension Labs API key for a new Universal API source. See Your API key.
  1. In the workflow editor, add the trigger node for your app, for example a new response, new review or new row.
  2. Run it once and check the output has three things: the customer’s text, an id for the record, and when it was written.

Use one source in Dimension Labs per app, so its data is easy to filter later.

n8n’s Code node can’t make HTTP requests (Using the Code node), so the work is split: a Code node builds each message, and an HTTP Request node sends it.

  1. Add a Code node after the trigger. Set the language to JavaScript and the mode to Run Once for All Items.
  2. Paste this code, then edit the pick lines so each one reads the right field from your trigger’s output, and set SOURCE to the app’s name.
// n8n Code node (JavaScript, Run Once for All Items).
// Builds one Dimension Labs message per input item. The HTTP Request node sends it.
const SOURCE = 'jotform'; // the app's name, kept in platformJson
// Edit the right-hand side of each line to match your trigger's fields.
const pick = (d) => ({
text: d.text, // the customer's words
recordId: d.id, // the record's own id: becomes sessionId
customerId: d.customerId, // optional: your internal customer id, never an email or name
writtenAt: d.createdAt, // when it was written, ideally with a time zone
extra: { rating: d.rating }, // anything else to filter or join on later
});
const clean = (s) => String(s).replace(/:/g, '-'); // ids can't contain colons
const out = [];
for (const item of $input.all()) {
const { text, recordId, customerId, writtenAt, extra } = pick(item.json);
if (!text || !String(text).trim()) continue; // skip empty text
const ts = typeof writtenAt === 'number' ? (writtenAt < 1e12 ? writtenAt * 1000 : writtenAt) : Date.parse(writtenAt);
if (Number.isNaN(ts)) throw new Error(`Can't read the date "${writtenAt}". Map a date with a time zone.`);
const sessionId = clean(`${SOURCE}-${recordId}`);
out.push({
json: {
endpoint: Date.now() - ts > 60 * 60 * 1000 ? 'trackhistorical' : 'track',
message: {
text: String(text),
userId: customerId ? clean(customerId) : sessionId,
incoming: true,
sessionId,
conversationId: sessionId,
dimensionlabs_timestamp: ts,
platformJson: { source: SOURCE, ...extra },
},
},
});
}
return out;

The code returns one item per record, each with the message and its endpoint: a record written more than an hour ago goes to /trackhistorical, as every guide does. A date given as a number in seconds is turned into milliseconds. Records with empty text are dropped.

Add an HTTP Request node after the Code node (HTTP Request node):

  1. Method: POST.
  2. URL: switch the field to an expression and enter https://tracker.dimensionlabs.io/{{ $json.endpoint }}
  3. Authentication: none. The API key goes in the query string.
  4. Turn on Send Query Parameters, choose Using Fields Below, and add:
NameValue
platformuniversal
v11.1.0-rest
typeincoming
apiKeyyour Dimension Labs API key
  1. Turn on Send Body. Set Body Content Type to JSON and Specify Body to Using JSON, and set the JSON field to the expression {{ JSON.stringify($json.message) }}. n8n sends Content-Type: application/json.

JSON.stringify escapes quotes and line breaks in the customer’s text, which is why this guide builds the message in code rather than typing the JSON by hand: a review with a quotation mark in it would break hand-typed JSON.

n8n runs the HTTP Request node once per item, so each record is its own POST. Run the node once with a test record. A 200 response means the message reached Dimension Labs.

  • Turn the workflow on. Each new record is sent as it arrives, to /track, and is enriched automatically every day.
  • If n8n sees a record late (more than an hour after it was written, for example on a polling trigger), the code sends it to /trackhistorical. Run a backfill from the Backfill tab to enrich those.
  • History: a trigger only sees new records. Export your history from the app and upload a file (check it with the file checker), then run a backfill.
  • Re-runs are safe: if you retry an execution, duplicates are removed automatically.

Personal data. Don’t put email addresses, names or phone numbers into extra: it is sent as platformJson. Redact the text if customers include personal details. See PII redaction.

If the trigger returns a whole conversation (a ticket with replies, a chat transcript), each message needs its own POST, in order, at least one second apart, with replies from your side marked incoming: false and type=outgoing. That is easier and more reliable in a script: see the app’s guide, or Any other system.

Checked against n8n’s documentation on 2026-10-26.