Custom Integration
The Custom integration connects JustAI to any system that can make an HTTP request — a homegrown messaging pipeline, an in-app surface, a website, or an ESP we don’t yet integrate with natively. Instead of JustAI pushing content into your ESP, your system calls the Generate API and uses the copy in the response.
How It Works
Section titled “How It Works”- Your system calls
POST /api/generate/:org_slugwith atemplate_id, auser_id, and (optionally) personalizationfields. - JustAI selects the best variant for that user — running the A/B split and ranking algorithms — and returns the copy as
copy.vars(e.g.subject,body). - Your system delivers the message through your own channel.
- You report downstream events (sends, opens, clicks, conversions) back to JustAI via webhooks or a data export, joined on the
tracking_id.
See the API Quickstart for authentication and key management.
On your template’s Configure tab, under Integration Settings:
- Set Integration to Custom.
- Choose your Templating Logic (see below).
- Configure the AB Test Configuration — for custom integrations we recommend AB Test Within JustAI (internal splitting) unless you already have your own experimentation system. See Template Configuration for the tradeoffs.
Templating Logic
Section titled “Templating Logic”Most copy needs personalization: “Hi Alice” instead of “Hi there”. To make that work, variants are authored with placeholders — markers in the text that get replaced with real values (a first name, a plan type, a discount amount) before the message is sent. The Templating Logic setting controls which placeholder syntax JustAI uses when writing your variants, and — just as importantly — where the placeholders get filled in: by JustAI at request time, or by your system after the response comes back.
Liquid
Section titled “Liquid”Liquid is a widely used templating language (originally from Shopify, also used by Customer.io and Braze). Placeholders are named variables in double curly braces, and the language supports conditional logic:
{% if first_name %}Hi {{ first_name }},{% else %}Hi there,{% endif %}your {{ plan_type }} plan is ready.With Liquid, JustAI renders the copy for you. Pass the values in the fields parameter of your Generate request:
{ "template_id": "welcome-email", "user_id": "user_123", "fields": { "first_name": "Alice", "plan_type": "premium" }}The response contains the final, ready-to-send text: "Hi Alice, your premium plan is ready." If a field is missing, the variant’s if/else fallback handles it gracefully ("Hi there, ...").
Choose Liquid if your system has the personalization values available at the time it calls the Generate API. This is the recommended default: you get named, readable placeholders, built-in fallbacks for missing values, and a response you can send as-is with no further processing.
Sprintf
Section titled “Sprintf”Sprintf uses numbered, positional placeholders — the %1$s-style format specifiers supported by printf-style formatters such as sprintf in PHP, String.format in Java, and POSIX printf in C:
Hi %1$s, your %2$s plan is ready.With Sprintf, JustAI does not render the copy. The response returns the text with the placeholders intact, and your system substitutes the values using its own formatter. Make sure your formatter supports the numbered %1$s syntax — for example, Python’s % operator does not, so Python clients should convert the placeholders first (e.g. %1$s → {0} and render with str.format).
Choose Sprintf if your system renders the copy itself — because the personalization values only exist inside your delivery pipeline (so you can’t pass them to the Generate API), or because your stack has no Liquid implementation to render with (e.g. PHP) — or if you already render printf-style strings, for example via a localization or message-catalog system.
Comparison
Section titled “Comparison”| Liquid | Sprintf | |
|---|---|---|
| Placeholder style | Named: {{ first_name }} | Positional: %1$s |
| Who fills in the values | JustAI, from the fields in your Generate request | Your system, after receiving the response |
| Missing-value fallbacks | Built in ({% if %}...{% else %}) | None — handle defaults in your code |
| Requirement | Field values must be available when you call the API | Your delivery code must format the string |
| Best for | Most integrations (recommended default) | Rendering the copy yourself: values only exist at send time, no Liquid library for your stack, or existing printf-style rendering |
Fields
Section titled “Fields”The placeholders available to your variants come from the fields defined in your template’s metadata (name plus a description of what the value contains). The AI only uses fields you’ve defined, and treats them as nullable. Fields are set up with the JustAI team during template creation — reach out if you need to add or change them.
Tracking
Section titled “Tracking”To measure performance, pass a stable tracking_id in each Generate request and use the same ID when reporting downstream events. If you don’t provide one, JustAI generates a UUID and returns it in the response — persist it so your events can be joined. We’ll work with your engineering team to pick an ID that matches your event model; see the Generate API for details.
Related Resources
Section titled “Related Resources”- API Quickstart — authentication and API keys
- Generate API — full request/response reference
- Webhooks — reporting events back to JustAI
- Template Configuration — A/B split options and thresholds