RudderStack
Use two RudderStack Webhook destinations to forward your RudderStack calls to JustAI. The JustAI Identify destination sends Identify calls that have a user ID to the Identify API, which creates or updates each person’s customer profile. The JustAI Track destination sends Track calls to the Track API, which records each one as a customer event. Each destination has a JavaScript transformation that passes on only the calls its endpoint accepts. The destinations forward only the calls RudderStack receives after you add them, so also plan how to load existing customers.
Owner: Engineering
Before you begin
Section titled “Before you begin”- You can create transformations and destinations in your RudderStack workspace. This setup uses two destinations and two JavaScript transformations.
- You have a JustAI API key for the environment you send to. See Create a key.
- You have your organization slug from your JustAI team. For a non-production environment, your JustAI team also gives you the environment’s path value, which replaces the slug, and its environment key for the
X-JustAI-Environmentheader. To send to more than one environment, see Send to production and a staging environment. - Your RudderStack calls carry the user ID you agreed to use in JustAI. See Identity and consent.
Why each destination needs a transformation
Section titled “Why each destination needs a transformation”A Webhook destination sends every call it receives to one URL, and its settings have no filter for call types. The transformations do three jobs:
- They filter call types. Each endpoint accepts one type of call. The Identify API doesn’t check the call type, so without a filter a Group call would write the group’s traits onto the person’s profile.
- They drop calls JustAI rejects. The Identify API needs a user ID and at least one trait, so the Identify transformation drops anonymous calls and calls with no traits.
- They move traits to where JustAI reads them. RudderStack SDKs send Identify traits in
context.traits. JustAI reads traits only from the top-leveltraitsobject, so an Identify call sent unchanged returns400. The Identify transformation copiescontext.traitsintotraits.
You can connect only one transformation to a destination, so each destination gets its own.
| Destination | Webhook URL | Its transformation passes on |
|---|---|---|
| JustAI Identify | https://ingest.justwords.ai/api/identify/{org_slug} |
Identify calls with a user ID and at least one trait |
| JustAI Track | https://ingest.justwords.ai/api/track/{org_slug} |
Track calls with an event name and a user ID or anonymous ID |
Create the transformations
Section titled “Create the transformations”Create both transformations first, so you can connect each one as soon as its destination exists.
-
In RudderStack, go to Collect > Transformations and select Create Transformation.
-
Name the transformation
JustAI Identify. -
Choose JavaScript as the language and select Create.
RudderStack opens the transformation’s Editor tab.
-
Replace the code in the editor with the Identify transformation, and select Save draft.
-
Test the transformation. See Test a transformation.
-
Select Publish.
-
Repeat these steps for a transformation named
JustAI Track, with the Track transformation.
Identify transformation
Section titled “Identify transformation”export function transformEvent(event, metadata) { if (event.type !== "identify") { return; }
const userId = typeof event.userId === "string" ? event.userId.trim() : ""; if (userId === "") { return; }
const traits = Object.assign({}, event.context && event.context.traits, event.traits); if (Object.keys(traits).length === 0) { return; }
event.userId = userId; event.traits = traits; return event;}The transformation:
- Drops every call that isn’t Identify. A transformation that returns nothing drops the call.
- Drops anonymous calls, where the user ID is missing or empty.
- Merges
context.traitsinto a top-leveltraitsobject. If a trait appears in both places, the top-level value wins. - Drops calls that have no traits in either place.
- Returns the event as the request body. JustAI reads
userId,traits,messageId, andtimestamp, and ignores the other RudderStack fields.
Track transformation
Section titled “Track transformation”export function transformEvent(event, metadata) { if (event.type !== "track") { return; }
if (typeof event.event !== "string" || event.event.trim() === "") { return; }
if (!event.userId && !event.anonymousId) { return; }
return event;}The transformation drops Page, Screen, Identify, Group, and Alias calls, and Track calls with no event name or no identity. A RudderStack Track call already has the shape the Track API accepts, so the transformation returns it unchanged. Anonymous Track calls are accepted, but only events with a userId can start or advance journeys. See Send customer events.
Test a transformation
Section titled “Test a transformation”-
In the transformation’s Editor tab, select + to create a test.
-
Under Input, select Import.
-
Choose the test input:
- To use recent calls from your source, choose Import from live event and select the calls.
- To test the Identify transformation without live traffic, choose Import existing payload. Select + next to Events, name the payload, paste the sample Identify call below, and select Create.
Sample Identify call {"type": "identify","messageId": "msg-0001","anonymousId": "anon-5678","userId": "user-1234","timestamp": "2026-10-01T12:00:00.000Z","context": {"traits": {"email": "ada@example.com","first_name": "Ada","plan": "pro"}}} -
Select Run.
-
Check the Actual output.
For the sample, the output is the same call with a top-level
traitsobject added:Actual {"type": "identify","messageId": "msg-0001","anonymousId": "anon-5678","userId": "user-1234","timestamp": "2026-10-01T12:00:00.000Z","context": {"traits": {"email": "ada@example.com","first_name": "Ada","plan": "pro"}},"traits": {"email": "ada@example.com","first_name": "Ada","plan": "pro"}}
Add the destinations
Section titled “Add the destinations”-
In RudderStack, open the source that sends your customer data, add a destination, and select Webhook from the list of destinations.
Choose Webhook, not HTTP Webhook. The settings on this page are for the Webhook destination.
-
Name the destination
JustAI Identifyand select Continue. -
Set the connection settings for JustAI Identify from the table below.
-
Open the destination’s Transformation tab, select Add a transformation, and Choose the
JustAI Identifytransformation. -
Repeat these steps for a destination named
JustAI Track, with the Track settings and theJustAI Tracktransformation.
| Setting | JustAI Identify | JustAI Track |
|---|---|---|
| Webhook URL | https://ingest.justwords.ai/api/identify/{org_slug} |
https://ingest.justwords.ai/api/track/{org_slug} |
| URL Method | POST |
POST |
| Headers | X-Api-Key with your API key as the value |
X-Api-Key with your API key as the value |
Replace {org_slug} with your organization slug in lowercase, or with the environment’s path value for a non-production environment. Don’t end the URL with a slash. RudderStack sends one event per request and adds content-type: application/json to POST requests, so you add only the X-Api-Key header.
For a non-production environment, add a second header, X-JustAI-Environment, with the environment key from your JustAI team. Leave it out for production. A header with an empty value returns 400.
Check your work
Section titled “Check your work”-
From your source, send an Identify call and a Track call for a test user, such as
user-1234with the emailada@example.com. For example, use a development build of your app.These are real calls. The Identify call creates or updates the test user’s profile in the environment your API key belongs to.
-
Open each destination’s Live Events tab and confirm that the call was delivered.
If a call failed, select it and read the Error Response. Then find the response in Fix common errors.
-
Read the test user’s profile back with the Profiles API. The command uses the
JUSTAI_ORG_SLUG,JUSTAI_ENVIRONMENT, andJUSTAI_API_KEYshell variables from Test your connection. For a non-production environment,JUSTAI_ORG_SLUGholds the environment’s path value andJUSTAI_ENVIRONMENTholds its environment key. For production,JUSTAI_ENVIRONMENTis empty, andcurlleaves the header out.Terminal window curl "https://ingest.justwords.ai/api/profiles/$JUSTAI_ORG_SLUG/user-1234" \-H "X-Api-Key: $JUSTAI_API_KEY" \-H "X-JustAI-Environment: $JUSTAI_ENVIRONMENT"The response is
200, andfieldsholds the traits from your test call. If a change isn’t there yet, wait a minute and read again. You can also search foruser-1234on Users in JustAI and open the row. -
In JustAI, open Events > Custom events and find your test event’s name.
New events can take time to appear. If an accepted event still doesn’t appear after you refresh, contact your JustAI team.
Load existing customers
Section titled “Load existing customers”The destinations forward only the calls RudderStack receives after you add them. A customer who makes no Identify call after that has no profile in JustAI. Before launch, load your existing customers’ profiles once with Hightouch or the Identify API from your backend. If you need a customer-specific file import, confirm its availability and procedure with your JustAI team before building it. Use the same user ID that your RudderStack calls carry.
Fix common errors
Section titled “Fix common errors”Identify errors list each problem in an issues array. Track errors give the first problem in error.
| Response | Cause | Fix |
|---|---|---|
400, “At least one trait is required unless consent is provided” |
The Identify call reached JustAI with its traits only in context.traits. |
Connect the published JustAI Identify transformation to the JustAI Identify destination. |
400, “String must contain at least 1 character(s)” or “Required” at userId |
An anonymous Identify call reached the Identify destination. | Connect the JustAI Identify transformation. |
400, Invalid literal value, expected "track" |
A call that isn’t Track reached the Track destination. | Connect the JustAI Track transformation to the JustAI Track destination. |
A 4xx response means the call or the setup needs a fix. Sending the same call again gets the same error. For authentication and URL errors, such as 401, 403, 404, Invalid org slug, and Invalid environment, see Errors and retries.
Send to production and a staging environment
Section titled “Send to production and a staging environment”Send each JustAI environment its calls through its own pair of destinations.
- Create a JustAI Identify and a JustAI Track destination for each JustAI environment, on the RudderStack source whose calls belong in that environment. Connect the same two transformations to each pair. One transformation can serve several destinations.
- In a non-production destination, put the environment’s path value in the Webhook URL in place of
{org_slug}, for examplehttps://ingest.justwords.ai/api/identify/acme_staging. Use an API key created in that environment, and add theX-JustAI-Environmentheader with the environment key. - Name each destination after its environment, such as
JustAI Identify staging. A key, path value, and header that point to different environments return403.
Avoid duplicate destinations
Section titled “Avoid duplicate destinations”Forward each source to each JustAI environment through one JustAI Identify destination and one JustAI Track destination. If two destinations forward the same source to the same endpoint and environment, turn one off.
