Email & MJML

Email on Inklura has three parts: Mail Designer, the app where you compose newsletters in MJML, the platform's sending service, and two Platform API routers: campaigns to manage and send campaigns, and emailAnalytics for reporting.

Mail Designer

Mail Designer (maildesigner.inklura.fr / mail.inklura.fr) composes newsletters in MJML, which compiles to HTML that mail clients render correctly, and keeps the MJML source for later editing. An AI assistant helps you draft the message. Mail Designer has its own newsletter programs and scheduling; you use it from its interface.

Managing and sending campaigns: the campaigns router

The Platform API's campaign lifecycle lives in the campaigns tRPC router, called at /api/trpc/campaigns.<procedure> using the tRPC conventions. Each procedure requires the listed permission:

Procedure Type Input Purpose Permission
getCampaigns query page, per_page, search, status List campaigns. campaigns:read
getCampaignById query id Fetch one campaign. campaigns:read
createCampaign mutation see below Create a campaign. campaigns:create
createCampaignWizard mutation channelType, details, template, audience, schedule Create a campaign with the guided wizard. campaigns:create
updateCampaign mutation createCampaign fields + id, status Update a campaign. campaigns:update
deleteCampaign mutation id Delete a campaign. campaigns:delete
sendCampaign mutation id Send a campaign. campaigns:send
pauseCampaign mutation id Set the campaign status to paused. campaigns:update
resumeCampaign mutation id Set the campaign status back to active. campaigns:update
duplicateCampaign mutation id Duplicate a campaign. campaigns:create
getCampaignActivity query id, page, per_page Read a campaign's activity, paginated. campaigns:read
getCampaignTags query none List campaign tags. campaigns:read
createCampaignTag mutation name Create a campaign tag. campaigns:create

Pagination starts at page: 0, with per_page: 10 by default. getCampaigns matches search against the name and description, and returns { data, total, page, per_page, totalPages }. The procedures that look up a campaign by id (except pauseCampaign and resumeCampaign) return NOT_FOUND for an unknown campaign or one that belongs to another site.

Creating a campaign

createCampaign accepts:

Field Type Notes
name string Required, at least 3 characters.
type string Required.
channelType string email or sms. Falls back to type, then email.
subject, content string Email subject and content.
templateId string Template to use.
segmentId string Contact segment to send to.
marketingCampaignId string Parent marketing campaign.
scheduled, scheduledDate boolean, date scheduled: true creates the campaign with status scheduled, otherwise draft.
testMode, testEmail boolean, string Test mode (false by default) and test address.

The response includes the campaign id.

curl -X POST "https://manage.inklura.fr/api/trpc/campaigns.createCampaign" \
  -H "Authorization: Bearer $INKLURA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"json":{"name":"October newsletter","type":"email","subject":"What is new this month","segmentId":"<segment-id>"}}'

Sending

sendCampaign sets the campaign status to active, then sends the message to every contact in the campaign's segments (minus any excluded segment), skipping unsubscribed addresses. Each send is logged and then feeds emailAnalytics. An SMS campaign goes out by SMS to the contacts who opted in. You do not call the sending service directly.

curl -X POST "https://manage.inklura.fr/api/trpc/campaigns.sendCampaign" \
  -H "Authorization: Bearer $INKLURA_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"json":{"id":"<campaign-id>"}}'

pauseCampaign and resumeCampaign only change the campaign status: they do not interrupt a send already started by sendCampaign.

Reporting: the emailAnalytics router

Reporting goes through a separate router, emailAnalytics. Every procedure requires a session that holds the analytics:read permission (see tRPC Procedures).

Procedure Main input Returns
getDashboardMetrics period filters Sends, unique opens and clicks, bounces, unsubscribes and their rates, compared with the previous period.
getCampaignAnalytics campaignId, includeTimeSeries, timeSeriesInterval Analytics for one campaign and its 50 most recent sent emails.
getCampaignRevenue campaignId, period (default 1y) Conversions, revenue, cost and ROAS attributed to a campaign.
getTopCampaigns limit (1 to 100, default 10), sortBy, sortOrder, period Best-performing campaigns.
getEngagementTrends period filters, granularity (default day) Engagement over time.
getProviderPerformance period filters Delivery performance.
getUnsubscribeAnalytics period filters Unsubscribe metrics.
getUnsubscribeFunnel period (7d, 30d or 90d), campaignId The unsubscribe funnel.
getHealthStatus none Status of the analytics service.

The period filters are:

Field Values Default
period today, yesterday, 7d, 30d, 90d, 1y, custom 30d
startDate, endDate dates, for period: "custom"
campaignId campaign UUID
emailAddress a recipient address
includeComparison boolean true

sortBy accepts openRate, clickRate, bounceRate or totalEmails (default openRate); sortOrder is asc or desc (default desc). timeSeriesInterval accepts hour, day, week or month (default hour), as does granularity.

curl -G "https://manage.inklura.fr/api/trpc/emailAnalytics.getDashboardMetrics" \
  -H "Authorization: Bearer $INKLURA_TOKEN" \
  --data-urlencode 'input={"json":{"period":"7d"}}'
Note

On failure, most procedures return an INTERNAL_SERVER_ERROR. Two degrade instead: getCampaignAnalytics still returns the campaign's sent emails, with analytics: null and an empty time series when the analytics service is unavailable, and getCampaignRevenue returns zeros with hasData: false. getHealthStatus reports each component as healthy or unhealthy, and the whole as healthy, degraded or unhealthy.

Open and click tracking

When tracking is enabled for a send (the sending service's default), the email carries a tracking pixel and its links go through a redirect. An open is counted when the pixel loads; a click is counted when the reader passes through the redirect to the destination page. These events feed emailAnalytics.

Related