Identity and consent
JustAI connects everything it knows about a person through two values: your user ID and their email address. The user ID joins customer profiles and customer events. The email address is how JustAI reaches the person in Iterable, and it is the address that email consent decisions apply to. Settle both before you connect a data source. JustAI identifies each profile by the exact user ID you send, so a different ID later creates a different person.
What to agree with your JustAI team
Section titled “What to agree with your JustAI team”Settle these points at kickoff:
- Which value you send as
userId, and that every source sends the same value. See Choose a stable user ID. - That
traits.emailholds the address Iterable knows each person by, and which Iterable project you connect. See Send the email address and Iterable project types. - Whether your organization treats each email address as one person.
- How your consent records map to decisions: channels, purposes, legal basis, source, and proof. See Consent decisions in Identify.
- Whether marketing consent is required before JustAI sends email, and for which regions. See Where consent takes effect.
- How unsubscribes recorded in Iterable reach your system of record. See Iterable subscriptions and unsubscribes.
- How you send requests to delete a person’s data. Your JustAI team handles these requests.
How JustAI matches a person
Section titled “How JustAI matches a person”| Data | JustAI matches it on |
|---|---|
| Customer profile, from the Identify API | userId |
| Customer event, from the Track API | userId, matched to the profile with the same user ID |
| Customer-specific profile file import | The user ID mapping confirmed by your JustAI team |
| CSV upload | The email column, plus the user_id column when you include one |
| Iterable recipient | traits.email on the profile |
| Email consent decision | traits.email on the profile |
| SMS consent decision | traits.phone on the profile |
Choose a stable user ID
Section titled “Choose a stable user ID”Use the ID your own systems give each person, one that never changes and is never reused for someone else. Send exactly the same value from every source: Identify, Track, file imports, and the user_id column in a CSV.
- Send it as a string. Send
"1234", not1234. Identify and Track reject a number. For a customer-specific file import, confirm the supported ID type with your JustAI team. - Match it character for character. JustAI compares IDs exactly. Identify removes leading and trailing spaces, but Track stores the ID as sent, so trim IDs in your source.
- Do not use values that change. Session IDs, device IDs, and other temporary values split one person into many profiles.
If your systems have no stable ID for each person, talk to your JustAI team before you connect a data source.
Send the email address
Section titled “Send the email address”Send each person’s email address as traits.email in Identify. JustAI identifies every recipient to Iterable by this address, on every channel. Iterable finds its user by that email, and sends texts and pushes to that user’s phone or devices. The address must be the one Iterable knows the person by. A person without an email address in JustAI can’t receive messages through Iterable, including SMS and push.
By default, two user IDs with the same email address stay two people. Ask your JustAI team whether treating each email address as one person is available and appropriate for your organization. Confirm that setup before relying on it. When it is enabled, an Identify call with an email address that already belongs to another profile joins the two, and both user IDs then read back the same profile. Placeholder values that are not real addresses, such as unknown or N/A, never join profiles.
Anonymous IDs
Section titled “Anonymous IDs”Some sources assign an anonymousId to visitors before they sign in. Track accepts an event with only an anonymousId, and the event appears in Events > Custom events. JustAI does not use anonymous IDs for anything else:
- Identify requires
userId. An Identify call with a missing, empty, ornulluserIdreturns400. Filter anonymous Identify calls out before they reach JustAI. - Identify ignores
anonymousId. JustAI has no alias call, and it never links earlier anonymous events to a profile. - An event with only an
anonymousIdnever starts, moves, or ends a journey, and never counts as a conversion.
Send the events you want journeys and measurement to use after the person has a user ID, and include that user ID.
Keep IDs consistent
Section titled “Keep IDs consistent”Check these points before you connect a full data source:
- The
userIdin Track matches theuserIdin Identify for the same person. If an event’s user ID has no profile, a journey run starts without the person’s traits or email address, and email steps can’t send to them. - Each person’s profile exists before their first event. Send Identify first.
- Every CSV upload has a
user_idcolumn, with the headeruser_idorUser ID. A header ofuserIddoes not count. Without it, a later Identify call with a user ID creates a second person. See Link people to your user ID. - For a customer-specific profile import, agree on an ID mapping that preserves the same user ID. See Amazon S3 file import.
traits.emailholds the address your Iterable project uses for the person.
To check all of this with one test person, see Test your connection.
Iterable project types
Section titled “Iterable project types”Iterable projects identify users by email address (email-based), by user ID (userID-based), or by either (hybrid). JustAI sends to Iterable by email address, so connect an email-based or hybrid project in Iterable’s US data center. JustAI does not support userID-based projects. If your project is userID-based, talk to your JustAI team before you plan your rollout.
For setup, this means:
- Every person you want to reach needs
traits.emailin JustAI, for every channel. - JustAI does not send your user ID to Iterable. The user IDs you send to JustAI do not need to match user IDs in your Iterable project.
See Connect Iterable for the rest of the Iterable setup.
Where consent takes effect
Section titled “Where consent takes effect”JustAI checks the consent decisions you send with Identify, and its own suppressions (people blocked from email in JustAI), before it hands an email to Iterable. These checks apply to email only. JustAI does not send email to people suppressed in JustAI. When your organization requires marketing consent, it also does not send email to people without it. A journey run then shows Not sent with “Marketing consent is missing.” or “Sending is blocked for this recipient.” The results of a blast, a one-time send from Blasts, group these people as Unsubscribed and No marketing consent under Not sent.
Your JustAI team confirms with you during onboarding whether marketing consent is required and for which regions.
Consent decisions do not appear in Users. Suppressions do. For a suppressed person, the Subscription column on Users reads Email suppressed, and the person’s page shows an Email badge under Suppressions. To suppress one person by hand, open them in Users, select Edit user, and turn off Email subscription.
Iterable subscriptions and unsubscribes
Section titled “Iterable subscriptions and unsubscribes”For email that JustAI sends through Iterable, Iterable owns unsubscribes:
- The unsubscribe link in each message is Iterable’s own. Iterable applies its subscription settings for the message type of your sending profile. Keep the unsubscribe link in the templates JustAI creates.
- Confirm with your JustAI team how Iterable unsubscribes reach your system of record and JustAI. Do not assume a change in one system updates the other or starts a subscription-change journey. Test an unsubscribe with an address you control, then verify the subscription state in Iterable and the suppression or consent state in JustAI before launch.
- For SMS sent through Iterable, Iterable handles STOP replies.
Keep your own system of record as the source of truth for consent. When a person’s consent changes there, send the decision to JustAI with Identify, and update the person’s subscription settings in Iterable to match.
Consent decisions in Identify
Section titled “Consent decisions in Identify”Identify accepts an optional consent array. Each entry records one decision for one channel. This call records that the person agreed to marketing email through a signup form:
{ "userId": "user-1234", "messageId": "user-1234:consent:2026-10-12T15:00:00Z", "timestamp": "2026-10-12T15:00:00Z", "traits": { "email": "ada@example.com" }, "consent": [ { "channel": "email", "status": "granted", "purpose": "marketing", "basis": "consent", "source": "signup_form", "consentedAt": 1791817200000, "proofRef": "newsletter-form-v3" } ]}Each decision needs a channel (email or sms) and a status (granted, withdrawn, or unknown). The optional fields record the purpose, the legal basis, where the decision came from, when the person made it, and what they agreed to. Unlike the call’s timestamp, consentedAt and expiresAt are epoch milliseconds, not ISO 8601 strings. For every field, its values, and the validation rules, see Consent decisions in the Identify API reference.
How JustAI applies decisions
Section titled “How JustAI applies decisions”- A decision applies to the address, not the user ID. Email decisions apply to
traits.email, trimmed and lowercased. SMS decisions apply totraits.phone. Include the address in the same call unless the profile already has it. If JustAI knows no address for the person, it skips the decision, and the call still returns200. - The newest decision wins. The decision time is
consentedAt. If you omit it, or set it more than 5 minutes in the future, JustAI uses the call’stimestampor the time it receives the call. When two decisions have the same time,withdrawnwins overgranted. A decision with statusunknownnever replaces an existing decision. - Implied consent expires. A granted
implied_transactiondecision lapses 2 years afterconsentedAt. A grantedimplied_inquirydecision lapses 6 months afterconsentedAt. A grantedimplied_contractdecision lapses at theexpiresAtyou send. If you send an earlierexpiresAtfor the first two, JustAI uses the earlier date. - Some combinations need more fields. A granted implied-consent decision requires
consentedAt, and a grantedimplied_contractdecision also requiresexpiresAt. See Validation rules. - Use a new
messageIdfor every consent change. JustAI does not compareconsentwhen it checks for a retry. A call that reuses an earlier ID with the sameuserId,timestamp, andtraitsreturns"duplicate": trueand drops the new decision.
To record a withdrawal from a preference center for a person whose profile already has an email address, send "traits": {} with the consent entry. For a user ID JustAI has not seen, this call creates an empty profile and skips the decision, because JustAI knows no address for it. When you are not sure the profile has the address, include traits.email in the call.
