Generate or revise template content with AI
Runs one AI action against a template and returns a validated draft. Dashboard session only: API keys are rejected with 403 ai_dashboard_only.
curl --request POST \
--url https://api.jetemail.com/marketing/ai/generate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"requestId": "<string>",
"templateId": "<string>",
"prompt": "<string>",
"tone": "Match the current brand and request",
"language": "English",
"history": [
{
"content": "<string>"
}
],
"context": {
"name": "<string>",
"subject": "<string>",
"previewText": "<string>",
"blocks": [
{}
],
"styles": {}
},
"target": {
"id": "<string>",
"type": "<string>",
"content": "<string>"
}
}
'import requests
url = "https://api.jetemail.com/marketing/ai/generate"
payload = {
"requestId": "<string>",
"templateId": "<string>",
"prompt": "<string>",
"tone": "Match the current brand and request",
"language": "English",
"history": [{ "content": "<string>" }],
"context": {
"name": "<string>",
"subject": "<string>",
"previewText": "<string>",
"blocks": [{}],
"styles": {}
},
"target": {
"id": "<string>",
"type": "<string>",
"content": "<string>"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
requestId: '<string>',
templateId: '<string>',
prompt: '<string>',
tone: 'Match the current brand and request',
language: 'English',
history: [{content: '<string>'}],
context: {
name: '<string>',
subject: '<string>',
previewText: '<string>',
blocks: [{}],
styles: {}
},
target: {id: '<string>', type: '<string>', content: '<string>'}
})
};
fetch('https://api.jetemail.com/marketing/ai/generate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.jetemail.com/marketing/ai/generate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'requestId' => '<string>',
'templateId' => '<string>',
'prompt' => '<string>',
'tone' => 'Match the current brand and request',
'language' => 'English',
'history' => [
[
'content' => '<string>'
]
],
'context' => [
'name' => '<string>',
'subject' => '<string>',
'previewText' => '<string>',
'blocks' => [
[
]
],
'styles' => [
]
],
'target' => [
'id' => '<string>',
'type' => '<string>',
'content' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.jetemail.com/marketing/ai/generate"
payload := strings.NewReader("{\n \"requestId\": \"<string>\",\n \"templateId\": \"<string>\",\n \"prompt\": \"<string>\",\n \"tone\": \"Match the current brand and request\",\n \"language\": \"English\",\n \"history\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"context\": {\n \"name\": \"<string>\",\n \"subject\": \"<string>\",\n \"previewText\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"styles\": {}\n },\n \"target\": {\n \"id\": \"<string>\",\n \"type\": \"<string>\",\n \"content\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.jetemail.com/marketing/ai/generate")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"requestId\": \"<string>\",\n \"templateId\": \"<string>\",\n \"prompt\": \"<string>\",\n \"tone\": \"Match the current brand and request\",\n \"language\": \"English\",\n \"history\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"context\": {\n \"name\": \"<string>\",\n \"subject\": \"<string>\",\n \"previewText\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"styles\": {}\n },\n \"target\": {\n \"id\": \"<string>\",\n \"type\": \"<string>\",\n \"content\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.jetemail.com/marketing/ai/generate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"requestId\": \"<string>\",\n \"templateId\": \"<string>\",\n \"prompt\": \"<string>\",\n \"tone\": \"Match the current brand and request\",\n \"language\": \"English\",\n \"history\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"context\": {\n \"name\": \"<string>\",\n \"subject\": \"<string>\",\n \"previewText\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"styles\": {}\n },\n \"target\": {\n \"id\": \"<string>\",\n \"type\": \"<string>\",\n \"content\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"replayed": true,
"requestId": "<string>",
"result": {
"kind": "subject_variants",
"message": "<string>",
"variants": [
{
"subject": "<string>",
"previewText": "<string>"
}
],
"blockId": "<string>",
"content": "<string>",
"html": "<string>",
"subject": "<string>",
"previewText": "<string>",
"blocks": [
{}
],
"styles": {}
},
"chat": {
"conversationId": "<string>",
"userMessage": {
"id": "<string>",
"requestId": "<string>",
"role": "user",
"content": "<string>",
"result": {
"kind": "subject_variants",
"message": "<string>",
"variants": [
{
"subject": "<string>",
"previewText": "<string>"
}
],
"blockId": "<string>",
"content": "<string>",
"html": "<string>",
"subject": "<string>",
"previewText": "<string>",
"blocks": [
{}
],
"styles": {}
},
"status": "pending",
"creditCost": 123,
"errorCode": "<string>",
"createdAt": 123,
"completedAt": 123
},
"assistantMessage": {
"id": "<string>",
"requestId": "<string>",
"role": "user",
"content": "<string>",
"result": {
"kind": "subject_variants",
"message": "<string>",
"variants": [
{
"subject": "<string>",
"previewText": "<string>"
}
],
"blockId": "<string>",
"content": "<string>",
"html": "<string>",
"subject": "<string>",
"previewText": "<string>",
"blocks": [
{}
],
"styles": {}
},
"status": "pending",
"creditCost": 123,
"errorCode": "<string>",
"createdAt": 123,
"completedAt": 123
}
},
"credits": {
"available": true,
"planLevel": 123,
"monthlyCredits": 123,
"granted": 123,
"reserved": 123,
"consumed": 123,
"remaining": 123,
"cycleKey": "2026-08",
"cycleEndsAt": 123,
"blocked": true,
"blockedReason": "<string>"
}
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted",
"retryAfter": 123
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}Authorizations
API key for account management endpoints. Use your api_ prefixed token.
Body
Total body size must stay under 75,000 bytes.
Idempotency key, stable across retries. Replaying one returns the original result without charging; reusing one with different input is a 409.
^[a-zA-Z0-9_-]{16,100}$Template to work on. Required.
Selects the task and the credit cost. rewrite_block and translate_block require target.
subject_variants, rewrite_block, translate_block, draft_email, template_chat, generate_template Required for every action except translate_block.
40008080Ignored; the server uses its own template-scoped history.
Show child attributes
Show child attributes
The live editor content, which is the source of truth for the request.
Show child attributes
Show child attributes
The selected block, for block-scoped actions. All three fields are required when present.
Show child attributes
Show child attributes
Response
Validated draft
true
True when the requestId was already completed; the stored result was returned and nothing was charged.
Validated AI output. Always a draft: applying it is a separate user action, and nothing here is saved or sent. kind selects the shape.
Show child attributes
Show child attributes
Show child attributes
Show child attributes
AI credit wallet for the authenticated owner, for the current monthly UTC cycle.
Show child attributes
Show child attributes
curl --request POST \
--url https://api.jetemail.com/marketing/ai/generate \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"requestId": "<string>",
"templateId": "<string>",
"prompt": "<string>",
"tone": "Match the current brand and request",
"language": "English",
"history": [
{
"content": "<string>"
}
],
"context": {
"name": "<string>",
"subject": "<string>",
"previewText": "<string>",
"blocks": [
{}
],
"styles": {}
},
"target": {
"id": "<string>",
"type": "<string>",
"content": "<string>"
}
}
'import requests
url = "https://api.jetemail.com/marketing/ai/generate"
payload = {
"requestId": "<string>",
"templateId": "<string>",
"prompt": "<string>",
"tone": "Match the current brand and request",
"language": "English",
"history": [{ "content": "<string>" }],
"context": {
"name": "<string>",
"subject": "<string>",
"previewText": "<string>",
"blocks": [{}],
"styles": {}
},
"target": {
"id": "<string>",
"type": "<string>",
"content": "<string>"
}
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
requestId: '<string>',
templateId: '<string>',
prompt: '<string>',
tone: 'Match the current brand and request',
language: 'English',
history: [{content: '<string>'}],
context: {
name: '<string>',
subject: '<string>',
previewText: '<string>',
blocks: [{}],
styles: {}
},
target: {id: '<string>', type: '<string>', content: '<string>'}
})
};
fetch('https://api.jetemail.com/marketing/ai/generate', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.jetemail.com/marketing/ai/generate",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'requestId' => '<string>',
'templateId' => '<string>',
'prompt' => '<string>',
'tone' => 'Match the current brand and request',
'language' => 'English',
'history' => [
[
'content' => '<string>'
]
],
'context' => [
'name' => '<string>',
'subject' => '<string>',
'previewText' => '<string>',
'blocks' => [
[
]
],
'styles' => [
]
],
'target' => [
'id' => '<string>',
'type' => '<string>',
'content' => '<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.jetemail.com/marketing/ai/generate"
payload := strings.NewReader("{\n \"requestId\": \"<string>\",\n \"templateId\": \"<string>\",\n \"prompt\": \"<string>\",\n \"tone\": \"Match the current brand and request\",\n \"language\": \"English\",\n \"history\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"context\": {\n \"name\": \"<string>\",\n \"subject\": \"<string>\",\n \"previewText\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"styles\": {}\n },\n \"target\": {\n \"id\": \"<string>\",\n \"type\": \"<string>\",\n \"content\": \"<string>\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.jetemail.com/marketing/ai/generate")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"requestId\": \"<string>\",\n \"templateId\": \"<string>\",\n \"prompt\": \"<string>\",\n \"tone\": \"Match the current brand and request\",\n \"language\": \"English\",\n \"history\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"context\": {\n \"name\": \"<string>\",\n \"subject\": \"<string>\",\n \"previewText\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"styles\": {}\n },\n \"target\": {\n \"id\": \"<string>\",\n \"type\": \"<string>\",\n \"content\": \"<string>\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.jetemail.com/marketing/ai/generate")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"requestId\": \"<string>\",\n \"templateId\": \"<string>\",\n \"prompt\": \"<string>\",\n \"tone\": \"Match the current brand and request\",\n \"language\": \"English\",\n \"history\": [\n {\n \"content\": \"<string>\"\n }\n ],\n \"context\": {\n \"name\": \"<string>\",\n \"subject\": \"<string>\",\n \"previewText\": \"<string>\",\n \"blocks\": [\n {}\n ],\n \"styles\": {}\n },\n \"target\": {\n \"id\": \"<string>\",\n \"type\": \"<string>\",\n \"content\": \"<string>\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"replayed": true,
"requestId": "<string>",
"result": {
"kind": "subject_variants",
"message": "<string>",
"variants": [
{
"subject": "<string>",
"previewText": "<string>"
}
],
"blockId": "<string>",
"content": "<string>",
"html": "<string>",
"subject": "<string>",
"previewText": "<string>",
"blocks": [
{}
],
"styles": {}
},
"chat": {
"conversationId": "<string>",
"userMessage": {
"id": "<string>",
"requestId": "<string>",
"role": "user",
"content": "<string>",
"result": {
"kind": "subject_variants",
"message": "<string>",
"variants": [
{
"subject": "<string>",
"previewText": "<string>"
}
],
"blockId": "<string>",
"content": "<string>",
"html": "<string>",
"subject": "<string>",
"previewText": "<string>",
"blocks": [
{}
],
"styles": {}
},
"status": "pending",
"creditCost": 123,
"errorCode": "<string>",
"createdAt": 123,
"completedAt": 123
},
"assistantMessage": {
"id": "<string>",
"requestId": "<string>",
"role": "user",
"content": "<string>",
"result": {
"kind": "subject_variants",
"message": "<string>",
"variants": [
{
"subject": "<string>",
"previewText": "<string>"
}
],
"blockId": "<string>",
"content": "<string>",
"html": "<string>",
"subject": "<string>",
"previewText": "<string>",
"blocks": [
{}
],
"styles": {}
},
"status": "pending",
"creditCost": 123,
"errorCode": "<string>",
"createdAt": 123,
"completedAt": 123
}
},
"credits": {
"available": true,
"planLevel": 123,
"monthlyCredits": 123,
"granted": 123,
"reserved": 123,
"consumed": 123,
"remaining": 123,
"cycleKey": "2026-08",
"cycleEndsAt": 123,
"blocked": true,
"blockedReason": "<string>"
}
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted",
"retryAfter": 123
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}{
"success": false,
"error": "<string>",
"code": "ai_credits_exhausted"
}