AI Personalization API
Generate AI-written email hooks and subject lines through the API. Learn when to use sync vs batch, the idempotency and polling patterns, pricing, and error codes.
Overview
The AI personalization endpoints generate two email variables per lead: an `ai_hook` (a short, curiosity-led opener) and an `ai_subject` (a subject line). Both are written by an LLM from the lead's own website data, in the locale you request. Each fresh generation costs £0.080; cache hits and failures are never charged. The hook and subject families share an identical contract — swap `ai/hook` for `ai/subject` and the response field `hook` for `subject`.
Sync vs Batch — which to use
Use the **synchronous** endpoint when you need one value immediately and can wait ~3 seconds: ```bash curl -X POST https://api.meirra.com/v1/ai/hook \ -H "x-api-key: mk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"leadId": "<lead-uuid>", "locale": "en", "mode": "native"}' ``` Use the **batch** endpoint for many leads (up to 100). It creates an async job, charges nothing at creation, and bills £0.080 per successful lead — failed leads are free. The lead must belong to you; unknown or other-customer leads return 404.
Polling a batch job
A batch request returns a `jobId` and a `pollUrl`. Poll `GET /v1/jobs/{id}` until `status` is `completed`, then read the per-lead results: ```bash # 1. Create the batch curl -X POST https://api.meirra.com/v1/ai/hook/batch \ -H "x-api-key: mk_live_your_key_here" \ -H "Content-Type: application/json" \ -d '{"leads": [{"leadId": "<uuid-1>"}, {"leadId": "<uuid-2>", "locale": "de", "mode": "translate"}]}' # 2. Poll the returned pollUrl curl https://api.meirra.com/v1/jobs/<jobId> \ -H "x-api-key: mk_live_your_key_here" ``` Succeeded leads carry a `hook`; failed leads do not and were not charged.
Idempotency
Send an `Idempotency-Key` header on any mutating request (especially `batch`) so a network retry never double-creates a job or double-charges. A replay within 24 hours returns the original response with `X-Idempotent-Replayed: true` and is not charged again. Reusing a key with a different body returns `409 IDEMPOTENCY_KEY_CONFLICT`; a key longer than 128 characters returns `400 INVALID_IDEMPOTENCY_KEY`. ```bash curl -X POST https://api.meirra.com/v1/ai/hook/batch \ -H "x-api-key: mk_live_your_key_here" \ -H "Idempotency-Key: my-batch-2026-05-29-001" \ -H "Content-Type: application/json" \ -d '{"leads": [{"leadId": "<lead-uuid>"}]}' ```
Node and Python examples
Minimal examples in Node and Python: **Node (fetch):** ```javascript const res = await fetch("https://api.meirra.com/v1/ai/hook", { method: "POST", headers: { "x-api-key": process.env.MEIRRA_API_KEY, "Content-Type": "application/json", }, body: JSON.stringify({ leadId, locale: "en" }), }); const { data } = await res.json(); console.log(data.hook); ``` **Python (requests):** ```python import os, requests res = requests.post( "https://api.meirra.com/v1/ai/hook", headers={"x-api-key": os.environ["MEIRRA_API_KEY"]}, json={"leadId": lead_id, "locale": "en"}, ) print(res.json()["data"]["hook"]) ```
Retrieve and list (free)
Reading previously-generated values never costs credits. Retrieve the most recent value for one lead with `GET /v1/ai/hook/{leadId}`, or list your generations with `GET /v1/ai/hook?limit=50&status=complete&locale=en`. The list is paginated (`limit` ≤ 100, `offset`) and filterable by `locale`, `status`, and `from` (ISO 8601). The value is `null` until its `status` is `complete`.
Error codes
AI generations never charge on failure. The codes you may see: • `LEAD_NOT_FOUND` (404) — the lead does not exist or is not yours • `NO_SCRAPE_DATA` (422) — no website data was available to generate from • `GENERATION_QUALITY_FAILED` (422) — output failed format rules after a retry • `UPSTREAM_TIMEOUT` / `UPSTREAM_UNAVAILABLE` (503) — the AI provider is busy; retry shortly • `INSUFFICIENT_BALANCE` (402) — not enough credit for the request (or whole batch) • `RATE_LIMIT_EXCEEDED` (429) — over 1000 requests/hour for the key
Discover capabilities
Call `GET /v1/ai/info` to read the live catalog — variables, pricing, supported locales, generation modes, and rate limit. Without an API key it returns the public catalog; with a valid key it also returns your balance and month-to-date AI spend. It is free and never charged.
Related Articles
API Billing
How credits, pricing, and pay-as-you-go billing work across all endpoints.
Rate Limits
The 1000 requests/hour per-key limit and how batch requests count against it.
API Authentication
Secure your API integration with proper authentication. Learn about API keys, headers, IP allowlists, and security best practices.