Skip to content

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

  • 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-Environment header. 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-level traits object, so an Identify call sent unchanged returns 400. The Identify transformation copies context.traits into traits.

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 both transformations first, so you can connect each one as soon as its destination exists.

  1. In RudderStack, go to Collect > Transformations and select Create Transformation.

  2. Name the transformation JustAI Identify.

  3. Choose JavaScript as the language and select Create.

    RudderStack opens the transformation’s Editor tab.

  4. Replace the code in the editor with the Identify transformation, and select Save draft.

  5. Test the transformation. See Test a transformation.

  6. Select Publish.

  7. Repeat these steps for a transformation named JustAI Track, with the Track transformation.

JustAI Identify
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.traits into a top-level traits object. 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, and timestamp, and ignores the other RudderStack fields.
JustAI Track
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.

  1. In the transformation’s Editor tab, select + to create a test.

  2. Under Input, select Import.

  3. 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"
    }
    }
    }
  4. Select Run.

  5. Check the Actual output.

    For the sample, the output is the same call with a top-level traits object 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"
    }
    }
  1. 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.

  2. Name the destination JustAI Identify and select Continue.

  3. Set the connection settings for JustAI Identify from the table below.

  4. Open the destination’s Transformation tab, select Add a transformation, and Choose the JustAI Identify transformation.

  5. Repeat these steps for a destination named JustAI Track, with the Track settings and the JustAI Track transformation.

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.

  1. From your source, send an Identify call and a Track call for a test user, such as user-1234 with the email ada@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.

  2. 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.

  3. Read the test user’s profile back with the Profiles API. The command uses the JUSTAI_ORG_SLUG, JUSTAI_ENVIRONMENT, and JUSTAI_API_KEY shell variables from Test your connection. For a non-production environment, JUSTAI_ORG_SLUG holds the environment’s path value and JUSTAI_ENVIRONMENT holds its environment key. For production, JUSTAI_ENVIRONMENT is empty, and curl leaves 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, and fields holds the traits from your test call. If a change isn’t there yet, wait a minute and read again. You can also search for user-1234 on Users in JustAI and open the row.

  4. 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.

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.

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 example https://ingest.justwords.ai/api/identify/acme_staging. Use an API key created in that environment, and add the X-JustAI-Environment header 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 return 403.

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.