mxAURA™Developer Center
GuidesExamples

Examples

All examples assume MXA_API_KEY in the environment. Base URL https://api.mxaura.ai/v1.

A minimal client

Node

js
const BASE = 'https://api.mxaura.ai/v1';
async function mxa(method, path, body, headers = {}) {
  const r = await fetch(BASE + path, { method, headers: { 'Authorization': `Bearer ${process.env.MXA_API_KEY}`, 'Content-Type': 'application/json', ...headers }, body: body ? JSON.stringify(body) : undefined });
  const j = await r.json();
  if (!r.ok) { const e = new Error(`${j.error?.code}: ${j.error?.message}`); e.status = r.status; e.retryAfter = Number(r.headers.get('Retry-After') || 0); throw e; }
  return j;
}

Python

python
import os, requests
BASE = 'https://api.mxaura.ai/v1'
S = requests.Session(); S.headers['Authorization'] = f"Bearer {os.environ['MXA_API_KEY']}"
def mxa(method, path, json=None, **headers):
    r = S.request(method, BASE + path, json=json, headers=headers)
    body = r.json()
    if not r.ok: raise RuntimeError(f"{body['error']['code']}: {body['error']['message']} (retry-after {r.headers.get('Retry-After')})")
    return body

Walk every page

js
async function* all(path) {
  let cursor = null;
  do {
    const j = await mxa('GET', `${path}${path.includes('?') ? '&' : '?'}limit=200${cursor ? '&cursor=' + cursor : ''}`);
    for (const row of j.data) yield row;
    cursor = j.meta?.next_cursor;
  } while (cursor);
}
for await (const a of all('/hubs/articles?status=published')) console.log(a.title);

Back off on 429

js
async function withBackoff(fn, tries = 5) {
  for (let i = 0; ; i++) {
    try { return await fn(); }
    catch (e) { if (e.status !== 429 || i >= tries) throw e; await new Promise(r => setTimeout(r, (e.retryAfter || 2 ** i) * 1000)); }
  }
}

Compose a message into a pool, idempotently

bash
curl -X POST "$BASE/pools/$POOL/messages" \
  -H "Authorization: Bearer $MXA_API_KEY" -H "Content-Type: application/json" \
  -H "Idempotency-Key: compose-welcome-2-$(date +%Y%m%d)" \
  -d '{ "message_id": "…", "template_id": "…", "header_id": "…", "summary_id": "…", "signature_id": "…", "sender_id": "…" }'

Run it twice: the second response is identical and carries Idempotent-Replayed: true.

See what a contact would receive

python
steps = mxa('POST', '/preview/simulate-campaign', {'campaignId': CAMPAIGN, 'contactId': '124303957916', 'maxSteps': 5})['data']
for s in steps: print(s['position'], s['pool_name'], '→', s['message_name'], s.get('reason', ''))

Enroll a contact (this sends email)

python
mxa('POST', f'/flows/{FLOW}/enroll', {'hs_contact_id': '124303957916'}, **{'Idempotency-Key': f'enroll-{FLOW}-124303957916'})

Needs enrollments.write. Counts toward the hourly cap; on 429 enrollment_cap wait Retry-After.

Find out why a send was blocked

bash
curl "$BASE/activity/dispatches?dispatch_status=blocked&days=7&limit=50" -H "Authorization: Bearer $MXA_API_KEY"

Each row carries a reason_code (no_sender, no_branding, reauth_required, campaign_disabled) plus the campaign and contact. Or register a webhook for dispatch.blocked and stop asking.

Publish an article to a hub

bash
# place it
curl -X POST "$BASE/hubs/$HUB/entries" -H "Authorization: Bearer $MXA_API_KEY" -H "Content-Type: application/json" -d '{ "article_id": "'$ART'" }'
# publish it
curl -X POST "$BASE/hubs/$HUB/entries/$ART/publish" -H "Authorization: Bearer $MXA_API_KEY"
# or schedule it
curl -X POST "$BASE/hubs/$HUB/entries/$ART/schedule" -H "Authorization: Bearer $MXA_API_KEY" -H "Content-Type: application/json" -d '{ "publish_at": "2026-09-10T13:00:00Z" }'

Needs publishing.write. The article.published webhook fires when it goes live.

Import an article with its original dates

bash
# Create it with the dates it had on the old site. created_at and published_at are the record's
# own stamps (the library's Created column, the editor); display_date is what readers see.
curl -X POST "$BASE/hubs/articles" -H "Authorization: Bearer $MXA_API_KEY" -H "Content-Type: application/json" \
  -d '{ "content_type_id": "'$TYPE'", "slug": "sell-assets-defer-the-taxes",
        "data": { "title": "Sell Assets, Defer the Taxes", "body": "<p>...</p>" },
        "created_at": "2020-03-01", "published_at": "2020-03-01", "display_date": "2020-03-01" }'

# Already imported? Back-date it in place. Only the keys you send change.
curl -X PUT "$BASE/hubs/articles/$ARTICLE" -H "Authorization: Bearer $MXA_API_KEY" -H "Content-Type: application/json" \
  -d '{ "created_at": "2020-03-01", "published_at": "2020-03-01" }'

Dates are YYYY-MM-DD (stored as noon UTC) or an ISO time. created_at is never cleared; published_at: null clears it. With created_at and no display_date on create, the display date follows created_at. None of these keys publishes anything: placing the article in a hub does. Needs articles.write. Over MCP the same keys are on compose_article and update_article.

Put the article text on your own page (for search and answer engines)

js
// In the function or worker that serves /insights/<slug>/ on your site.
const r = await fetch(`https://hubs.mxaura.ai/e/${EMBED_KEY}/${slug}/content.json`, { redirect: "manual" });
if (r.status === 404) return new Response("Not found", { status: 404 });           // not the gallery with a 200
if (r.status === 301) return Response.redirect((await r.json()).moved_to.url, 301); // the slug was renamed
if (!r.ok) return lastGoodCopy(slug) ?? new Response("Try again shortly", { status: 503, headers: { "Retry-After": "120" } });
const a = await r.json();
// 1. head: <title>${a.title}</title>, description, canonical ${a.url},
//          <script type="application/ld+json">${JSON.stringify(a.jsonld)}</script>
// 2. body: put a.html INSIDE the mount element, before embed.js runs:
//          <div data-mxa-hub="EMBED_KEY" data-mode="path" data-path="/insights/">${a.html}</div>

embed.js shows that HTML until the gallery is up, then hides it. If the gallery never loads the article stays on screen. No credential: the address is public, like the gallery. Details under Public rendering.

Let a reviewer see drafts on the live page for an hour

bash
curl -X POST "$BASE/hubs/$HUB/preview" -H "Authorization: Bearer $MXA_API_KEY" -H "Content-Type: application/json" -d '{ "minutes": 60 }'

The live embed shows drafts, noindex, uncached, for 60 minutes; { "minutes": 0 } closes it early. Needs publishing.write.

Register a webhook and test it

bash
curl -X POST "$BASE/webhooks" -H "Authorization: Bearer $MXA_API_KEY" -H "Content-Type: application/json" \
  -d '{ "url": "https://hooks.example.com/mxaura", "events": ["dispatch.sent", "dispatch.blocked"] }'
# → { "data": { "id": "…", "secret": "whsec_…", … } }   store the secret now; it is not shown again
curl -X POST "$BASE/webhooks/$ID/test" -H "Authorization: Bearer $MXA_API_KEY"

Make / Zapier / n8n

Use an HTTP module with Authorization: Bearer <key>; the JSON envelope maps directly. For events, the platform's "catch webhook" URL is the endpoint you register. mxAURA's own Make connector, when installed, wraps the same API.