POST /v1/app-ad-creatives/generate
GET /v1/app-ad-creatives/jobs/:jobId
- confirmed product key points
- paste-ready Meta primary text, headline, description, and call to action
- a square
1024x1024PNG creative generated from the app’s real icon and screenshots - the final prompt used to generate the creative
POST /v1/app-ad-creatives/generate returns a jobId immediately with HTTP 202; poll GET /v1/app-ad-creatives/jobs/:jobId until the job is completed or failed.
Generated creatives use real listing assets as references. When screenshots are available, Appeeky composites the actual app UI into the creative instead of inventing unrelated product screens.
Create a creative job
POST /v1/app-ad-creatives/generate
Request body
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
appUrl | string | Conditional | — | App Store or Google Play listing URL. Required unless platform + appId are provided. |
platform | string | Conditional | — | apple or google. Required when using appId instead of appUrl. |
appId | string | Conditional | — | Apple numeric app ID or Google Play package name. Required when using platform. |
country | string | No | us | Storefront country, ISO 3166-1 alpha-2. |
lang | string | No | en | Google Play language code. |
mode | string | No | generate | analyze, generate, or edit. |
style | string | No | ugc | Creative direction. Built-ins: ugc, professional, problem_solution, before_after, lifestyle. Custom strings are also accepted. |
imagePreset | string | No | branded_showcase | Composition preset. See Image presets. |
angle | string | No | inferred | Optional ad angle, e.g. problem-solution for busy founders. |
audience | string | No | inferred | Optional target audience override. |
keyPoints | object | No | inferred | User-confirmed product facts to steer the ad. |
extraScreenshotUrls | string[] | No | [] | Additional public screenshots to use as visual references. |
generateImage | boolean | No | true | Set false to only analyze the listing and generate copy. |
quality | string | No | medium | Image quality: low, medium, or high. |
editInstruction | string | Required for edit | — | Natural-language edit instruction, e.g. Make the headline bigger and use a navy background. |
previousAd | object | No | — | Previous ad object when using mode: "edit". |
Credits
Appeeky separates normal API credits from creative credits.| Mode | Bucket | Cost | Notes |
|---|---|---|---|
analyze | API credits | 1 | Listing analysis + key points + copy, no image. |
generateImage: false | API credits | 1 | Copy-only run, regardless of mode. |
generate | Creative credits | low: 1, medium: 2, high: 5 | New square ad image + copy. |
edit | Creative credits | low: 1, medium: 2, high: 5 | Modify an existing image ad with a sentence. |
You can pass
X-OpenAI-Key to use your own OpenAI key. BYOK image jobs use 1 API credit and do not consume creative credits. The key is not stored in the job record.Image presets
| Preset | Best for | What it creates |
|---|---|---|
branded_showcase | Product-first launch ads | App icon/name, large headline, exactly one hero phone mockup with a real screenshot, and benefit callouts. |
person_holding_phone | Lifestyle/people ads | A realistic person or hands holding a phone, with the real app UI composited on screen and text in negative space. |
creator_testimonial | UGC/testimonial ads | A creator-style or diary-style ad with a short quote, app lockup, and real app screen. |
problem_solution_split | Direct-response ads | A before/after or problem/solution split layout with the app as the answer. |
clean_app_store_mockup | Premium store/social hybrids | Minimal whitespace, crisp phone mockup, icon, headline, and short subhead. |
MCP tools
The same workflow is available through the Appeeky MCP Server:| Tool | Description |
|---|---|
generate_app_ad_creative | Starts an async app ad creative job. Supports the same mode, style, image_preset, angle, and quality options. |
get_app_ad_creative_job | Polls the job and returns the generated image URL, Meta copy, key points, and final prompt when complete. |
Code examples
curl -X POST "https://api.appeeky.com/v1/app-ad-creatives/generate" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"appUrl": "https://apps.apple.com/us/app/forest-focus-for-productivity/id866450515",
"country": "us",
"mode": "generate",
"style": "ugc",
"imagePreset": "person_holding_phone",
"angle": "problem-solution for people distracted by their phones",
"audience": "students and knowledge workers"
}'
const start = await fetch("https://api.appeeky.com/v1/app-ad-creatives/generate", {
method: "POST",
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json",
},
body: JSON.stringify({
appUrl: "https://apps.apple.com/us/app/forest-focus-for-productivity/id866450515",
country: "us",
mode: "generate",
style: "ugc",
imagePreset: "person_holding_phone",
}),
});
const { data } = await start.json();
const jobId = data.jobId;
async function pollCreative() {
const res = await fetch(
`https://api.appeeky.com/v1/app-ad-creatives/jobs/${jobId}`,
{ headers: { "X-API-Key": "YOUR_API_KEY" } }
);
const { data } = await res.json();
if (data.status === "completed" || data.status === "failed") return data;
await new Promise((resolve) => setTimeout(resolve, 4000));
return pollCreative();
}
console.log(await pollCreative());
import time, requests
headers = {"X-API-Key": "YOUR_API_KEY"}
start = requests.post(
"https://api.appeeky.com/v1/app-ad-creatives/generate",
headers={**headers, "Content-Type": "application/json"},
json={
"platform": "google",
"appId": "com.spotify.music",
"country": "us",
"lang": "en",
"mode": "generate",
"style": "professional",
"imagePreset": "clean_app_store_mockup",
},
)
job_id = start.json()["data"]["jobId"]
while True:
job = requests.get(
f"https://api.appeeky.com/v1/app-ad-creatives/jobs/{job_id}",
headers=headers,
).json()["data"]
if job["status"] in ("completed", "failed"):
break
time.sleep(4)
print(job)
Response (202 Accepted)
{
"data": {
"jobId": "4b8419b6-0d3a-4ab7-a8e8-6d1f4b53d414",
"triggerRunId": "run_abc123",
"status": "queued",
"mode": "generate"
}
}
Poll job status
GET /v1/app-ad-creatives/jobs/:jobId
Response while running
{
"data": {
"jobId": "4b8419b6-0d3a-4ab7-a8e8-6d1f4b53d414",
"status": "processing",
"mode": "generate",
"input": {
"appUrl": "https://apps.apple.com/us/app/forest-focus-for-productivity/id866450515",
"country": "us",
"mode": "generate",
"style": "ugc",
"imagePreset": "person_holding_phone"
},
"result": null,
"error": null,
"triggerRunId": "run_abc123",
"createdAt": "2026-06-25T08:42:11.000Z",
"updatedAt": "2026-06-25T08:42:16.000Z"
}
}
Response when completed
{
"data": {
"jobId": "4b8419b6-0d3a-4ab7-a8e8-6d1f4b53d414",
"status": "completed",
"mode": "generate",
"result": {
"listing": {
"platform": "apple",
"appId": "866450515",
"country": "us",
"lang": null,
"title": "Forest: Focus for Productivity",
"developer": "SEEKRTECH CO., LTD.",
"url": "https://apps.apple.com/us/app/id866450515",
"iconUrl": "https://...",
"description": "Stay focused, be present...",
"category": "Productivity",
"rating": 4.8,
"reviewsCount": 424000,
"isFree": false,
"screenshots": ["https://...", "https://..."]
},
"keyPoints": {
"whatItDoes": "Helps users stay off their phone and focus by growing virtual trees.",
"targetAudience": "Students and knowledge workers who get distracted by their phones.",
"painPoint": "They keep losing focus to quick phone checks.",
"promise": "Turn focused time into a simple visual reward.",
"brandTone": "Calm, motivating, nature-inspired.",
"visualDirection": "Show real app screens inside a clean phone mockup with a focus-progress hook.",
"adAngle": "Problem-solution"
},
"assets": {
"iconUrl": "https://...",
"screenshotUrls": ["https://...", "https://..."],
"referenceImageCount": 4
},
"ad": {
"id": "cb02a6a2-b01f-43b3-a02f-58b4863d9f8e",
"style": "ugc",
"imagePreset": "person_holding_phone",
"angle": "Problem-solution",
"imageUrl": "https://assets.appeeky.com/app-ad-creatives/cb02.../square.png",
"width": 1024,
"height": 1024,
"format": "png",
"copy": {
"primaryText": "Your phone keeps pulling you away from deep work. Forest turns focus into a tiny reward: plant a tree, stay present, and watch your progress grow.",
"headline": "Grow your focus",
"description": "Stay off your phone and get more done.",
"callToAction": "DOWNLOAD"
},
"creativeHeadline": "Stop checking your phone",
"creativeSubhead": "Grow a tree every time you stay focused.",
"prompt": "Create a square 1024x1024 Meta/Instagram ad creative...",
"generatedAt": "2026-06-25T08:43:04.000Z"
}
},
"error": null,
"triggerRunId": "run_abc123",
"createdAt": "2026-06-25T08:42:11.000Z",
"updatedAt": "2026-06-25T08:43:04.000Z"
}
}
Job fields
| Field | Type | Description |
|---|---|---|
status | string | queued, processing, completed, or failed. |
mode | string | The requested mode: analyze, generate, or edit. |
input | object | The safe job input. Sensitive BYOK values are not stored here. |
result | object | The completed creative payload. null until the job completes. |
error | string | Failure message when status is failed; otherwise null. |
triggerRunId | string | Trigger.dev run identifier for support/debugging. |
Edit an existing ad
Usemode: "edit" with a previous ad object and a natural-language instruction.
cURL
curl -X POST "https://api.appeeky.com/v1/app-ad-creatives/generate" \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"appUrl": "https://apps.apple.com/us/app/forest-focus-for-productivity/id866450515",
"mode": "edit",
"editInstruction": "Make the headline bigger and change the background to navy.",
"previousAd": {
"style": "ugc",
"creativeHeadline": "Stop checking your phone",
"creativeSubhead": "Grow a tree every time you stay focused."
}
}'
Errors
| Status | Code | When |
|---|---|---|
| 400 | INVALID_REQUEST | Missing or invalid app URL, app ID, platform, or edit instruction. |
| 401 | MISSING_AUTH | No Authorization: Bearer <token> or X-API-Key header. |
| 401 | INVALID_API_KEY | Invalid or inactive API key. |
| 403 | PRO_FEATURE | The API key owner is not on a Pro plan. |
| 404 | APP_NOT_FOUND | The app listing could not be found in the requested storefront. |
| 404 | JOB_NOT_FOUND | The requested job ID does not exist. |
| 503 | OPENAI_NOT_CONFIGURED | Server-side OpenAI credentials are not configured and no X-OpenAI-Key was provided. |

