Betav1 endpoints are open for early integrations. Additive fields may ship before GA.
The ad-creative API for builders.
Turn a brand and an idea into finished, on-brand creative — meme ads, images, short-form video, carousels, storyboards. The same engine behind studio.memes.media, as a clean REST API. One key, one async pattern, a handful of calls to a campaign.
Images & memes
Brand-grounded ad images, 1–4 variants, with edits, inpaint, and reframe.
Short-form video
Text-to-video and image-to-video — animate any asset you generate.
Carousels & storyboards
Free strategy plan, then render multi-slide carousels and narrative storyboards.
Brand kits & audits
Reusable brand profiles that ground every call, plus website-grounded audits.
Three ideas, and you know the whole API
| One async pattern | Every creative call returns a Generation you poll (or receive by webhook). You never block on a render. |
| One asset shape | Every output — image, video, slide, analysis — is the same normalized Asset. Write your handling once. |
| One brand context | Pass a brand_kit_id (or inline brand_context) to any endpoint and the output is on-brand by construction. |
Quickstart
Generate your first meme in two calls. Create a key in API settings, then:
1 · Generate
Every creative call is asynchronous. You get an immediate 202 with a queued job.
curl https://api.memes.media/v1/memes \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 3f1c9a52-0e9b-4b8d-9a1a-1f2e3d4c5b6a" \
-d '{
"prompt": "When the coffee finally kicks in on a Monday",
"brand_context": { "company_name": "Dawn Roasters", "industry": "coffee" },
"aspect_ratio": "1:1",
"count": 2
}'const res = await fetch("https://api.memes.media/v1/memes", {
method: "POST",
headers: {
Authorization: `Bearer ${process.env.MEMES_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": crypto.randomUUID(),
},
body: JSON.stringify({
prompt: "When the coffee finally kicks in on a Monday",
brand_context: { company_name: "Dawn Roasters", industry: "coffee" },
aspect_ratio: "1:1",
count: 2,
}),
});
const { generation } = await res.json();
console.log(generation.id); // gen_8f3k1m2p7qimport os, uuid, requests
res = requests.post(
"https://api.memes.media/v1/memes",
headers={
"Authorization": f"Bearer {os.environ['MEMES_API_KEY']}",
"Idempotency-Key": str(uuid.uuid4()),
},
json={
"prompt": "When the coffee finally kicks in on a Monday",
"brand_context": {"company_name": "Dawn Roasters", "industry": "coffee"},
"aspect_ratio": "1:1",
"count": 2,
},
)
generation = res.json()["generation"]
print(generation["id"]) # gen_8f3k1m2p7q2 · Poll for the result
Poll the unified Generations endpoint until status is terminal. In production, register a webhook instead.
curl https://api.memes.media/v1/generations/gen_8f3k1m2p7q \
-H "Authorization: Bearer sk_live_YOUR_KEY"{
"generation": {
"id": "gen_8f3k1m2p7q",
"type": "meme",
"status": "succeeded",
"model": "forge-image",
"completed_count": 2,
"output": [
{ "id": "asset_a1", "type": "image", "url": "https://cdn.memes.media/a1.png", "aspect_ratio": "1:1", "width": 1024, "height": 1024 },
{ "id": "asset_a2", "type": "image", "url": "https://cdn.memes.media/a2.png", "aspect_ratio": "1:1", "width": 1024, "height": 1024 }
],
"completed_at": "2026-06-18T17:04:41Z"
},
"usage": { "credits_used": 2, "credits_remaining": 478 },
"meta": { "request_id": "req_b2c4", "livemode": true }
}That's the entire loop: submit → poll → use output[]. It's identical for images, video, carousels, and storyboards — only the request body changes.
A complete campaign
A realistic flow: save a brand once, generate variants, then resize the winner for Stories. Watch each id thread into the next call — a brand_kit_id grounds the generation, and an output[].id (asset_…) becomes the input to the reframe.
# 1 · Save the brand once — the returned id is reusable forever
curl https://api.memes.media/v1/brand-kits \
-H "Authorization: Bearer sk_live_YOUR_KEY" -H "Content-Type: application/json" \
-d '{ "name": "Dawn Roasters", "company_name": "Dawn Roasters",
"website_url": "https://dawnroasters.example",
"brand_colors": ["#3B2A1A", "#E8C39E"], "tone_of_voice": "warm, witty" }'
# -> { "brand_kit": { "id": "bk_dawn_roasters", ... } }
# 2 · Generate four on-brand variants
curl https://api.memes.media/v1/memes \
-H "Authorization: Bearer sk_live_YOUR_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: 9b1d..." \
-d '{ "prompt": "POV: cold brew the night before a deadline",
"brand_kit_id": "bk_dawn_roasters", "count": 4 }'
# -> { "generation": { "id": "gen_8f3k1m2p7q", "status": "queued" } }
# 3 · Poll until terminal
curl https://api.memes.media/v1/generations/gen_8f3k1m2p7q \
-H "Authorization: Bearer sk_live_YOUR_KEY"
# -> status "succeeded", output: [ { "id": "asset_a1", ... }, ... ]
# 4 · Reframe the winner for Stories — any output asset can be reused as an input
curl https://api.memes.media/v1/images/reframe \
-H "Authorization: Bearer sk_live_YOUR_KEY" -H "Content-Type: application/json" \
-d '{ "image_id": "asset_a1", "aspect_ratio": "9:16" }'From here, animate the winner into video (POST /videos/animate), or fan out a carousel from the same brand kit. Every output asset is reusable as the next call's input.
Authentication
The API authenticates with secret keys sent as a bearer token.
curl https://api.memes.media/v1/account \
-H "Authorization: Bearer sk_live_YOUR_KEY"| Live keys | sk_live_… — bill and affect your live workspace. |
| Test keys | sk_test_… — run the same code paths in a sandbox; outputs are watermarked. |
| Visibility | The full secret is shown once at creation. We store only a one-way hash. |
| Rotation | Create a new key, deploy it, then revoke the old one. Revocation is immediate. |
Every key belongs to a workspace. The livemode boolean on every response tells you which mode a key is in.
Keep keys server-side. Secret keys grant full access to a workspace's generation and billing — never embed them in browser, mobile, or other client-side code. If a key leaks, revoke it immediately. A missing or invalid key returns 401 authentication_error.
Making requests
Base URL & versioning
All requests go to https://api.memes.media/v1. The major version is in the path; breaking changes ship as /v2 and never under you. Pin dated, backwards-compatible refinements with a header:
Memes-Version: 2026-06-18Idempotency
Safely retry any POST with an Idempotency-Key header (a UUID per logical operation). We cache the first response for 24 hours and replay it on retries — a dropped connection never double-charges or double-generates. Reusing a key with a different body returns 409 idempotency_conflict.
Rate limits
Each key gets a sliding-window limit. Every response carries the current state:
RateLimit-Limit: 120
RateLimit-Remaining: 118
RateLimit-Reset: 41Exceeding it returns 429 rate_limited with a Retry-After header. This is separate from your credit quota — hitting your plan's credit ceiling returns 429 quota_exceeded instead.
Pagination
List endpoints are cursor-paginated and consistent everywhere.
curl "https://api.memes.media/v1/memes?limit=40&starting_after=asset_a2" \
-H "Authorization: Bearer sk_live_YOUR_KEY"{ "data": [ /* ... */ ], "has_more": true, "next_cursor": "asset_xy9" }| Param | Type | Description |
|---|---|---|
limit | integer | Page size, 1–100. Default 40. |
starting_after | string | Object id to start after (from next_cursor). |
q | string | Free-text search, ≤200 chars, where supported. |
order | enum | newest (default) or oldest. |
The cursor is always the id of the last object in the page you received — pass it as starting_after for the next page, and stop when has_more is false.
Generations
A Generation is the single resource behind every long-running operation. Whether you render one image or a ten-slide carousel, you get a Generation and read results from it.
Lifecycle
POST /v1/<resource> -> 202 { generation: { status: "queued" } }
GET /v1/generations/{id} -> 200 { generation: { status, output } }
webhook generation.completed -> push (optional)Status values
| Status | Meaning |
|---|---|
| queued | Accepted and credits reserved; not started yet. |
| processing | Actively rendering. |
| succeeded | All requested outputs produced. |
| partial | Some of N outputs succeeded; unfilled credits are refunded. |
| failed | Terminal failure; reserved credits are refunded. |
| canceled | Canceled before completion. |
succeeded, partial, failed, and canceled are terminal — stop polling once you reach one.
Credits
Credits are reserved when a job is queued and settle when it completes — you're charged only for delivered outputs, and reserved credits are refunded on failed, canceled, or the unfilled part of a partial. That's why a job reads credits_used: 0 at submit and the final figure once terminal. Every response carries a usage block: { credits_used, credits_remaining, interval, reset_at }.
The Generation object
{
"id": "gen_8f3k1m2p7q",
"object": "generation",
"type": "meme",
"status": "succeeded",
"model": "forge-image",
"requested_count": 4,
"completed_count": 4,
"failed_count": 0,
"output": [ /* Asset objects */ ],
"error": null,
"created_at": "2026-06-18T17:04:22Z",
"completed_at": "2026-06-18T17:04:53Z"
}type is one of meme, image, edit, reframe, video, carousel, storyboard.
The Asset object
Every output, for every endpoint, has the same shape:
{
"id": "asset_a1",
"type": "image",
"url": "https://cdn.memes.media/a1.png",
"thumbnail_url": "https://cdn.memes.media/a1_thumb.png",
"aspect_ratio": "1:1",
"width": 1024,
"height": 1024,
"slide_index": null,
"parent_id": null,
"model": "forge-image",
"created_at": "2026-06-18T17:04:41Z"
}type is image, video, carousel_slide, or analysis. slide_index is set for carousel slides; parent_id links edits and reframes to their source.
Endpoints
Poll every 2–3s and stop at the first terminal status. Images and memes typically finish in 10–30s, video in 1–4 minutes. In production, prefer a webhook.
Models
Set model to pick a model, or omit it for the smart default per endpoint. Models belong to the Forge family — each named by capability, with a faster -fast variant where one is offered.
| Model | Best for |
|---|---|
forge-image | Primary text-to-image ad creative; reference, product, and logo conditioning. default for Images & Memes |
forge-image-fast | Faster, cheaper image generation — quick variants and iteration. |
forge-edit | Instruction edits, mask inpainting, and aspect-ratio reframing. |
forge-video | Text-to-video and multi-reference (2–4 image) video. |
forge-motion | Image-to-video — animate a single existing asset. |
forge-prompt | Prompt enhancement — rough idea to production-ready brief. |
forge-plan | Carousel strategy planning. |
forge-copy-fast | Fast brand/creative analysis (e.g. URL analysis). |
Most endpoints pick the right model for you — you only set model to choose between forge-image and forge-image-fast. A Forge id routes to the best available engine and fails over automatically; your code references only the stable id, and we improve what's behind it without changing the contract.
Errors
The API uses conventional HTTP status codes and returns a single error envelope.
{
"error": {
"type": "invalid_request_error",
"code": "missing_required_param",
"message": "Either prompt, brand_context, or reference_images is required.",
"param": "prompt",
"request_id": "req_8f2a1c"
}
}| HTTP | Type | Common codes | When |
|---|---|---|---|
| 400 | invalid_request_error | missing_required_param, invalid_aspect_ratio | Malformed or missing input. |
| 401 | authentication_error | invalid_api_key, revoked_api_key | Bad or missing key. |
| 403 | permission_error | insufficient_scope, plan_feature_unavailable | Key lacks a scope, or feature not on plan. |
| 404 | not_found_error | resource_not_found | Unknown or unowned id. |
| 409 | conflict_error | idempotency_conflict | Idempotency reuse with a new body. |
| 422 | generation_error | content_blocked, generation_failed | Safety block or render failure. |
| 429 | rate_limit_error | rate_limited | Per-key rate limit. See Retry-After. |
| 429 | quota_error | quota_exceeded | Credit or feature quota exhausted. |
| 500 | api_error | internal_error | Unexpected error on our side. |
| 503 | service_unavailable | temporarily_unavailable | At capacity; retry shortly. |
Retry around 429 (respect Retry-After) and 503 (exponential backoff). 400–404 aren't retryable without changes.
Webhooks
Skip polling: register an HTTPS endpoint and we'll POST a signed event when a job reaches a terminal state.
| Event | Fires when |
|---|---|
generation.completed | A job succeeded. |
generation.partial | A job finished with some outputs. |
generation.failed | A job failed or timed out. |
generation.canceled | A job was canceled. |
Payload
{
"id": "evt_2x9k",
"type": "generation.completed",
"created_at": "2026-06-18T17:04:53Z",
"livemode": true,
"data": { "generation": { /* full Generation object */ } }
}Verifying signatures
Every delivery is signed with your endpoint's secret (whsec_…, shown once) and carries svix-id, svix-timestamp, and svix-signature headers. The simplest way to verify is the official libraries — JS/TS, Python, Go, Rust, Ruby, PHP, Java, C#, and more:
import { Webhook } from "svix"; // npm install svix
const wh = new Webhook(process.env.MEMES_WEBHOOK_SECRET); // whsec_…
// Pass the RAW request body + the svix-* headers.
const event = wh.verify(rawBody, {
"svix-id": req.headers["svix-id"],
"svix-timestamp": req.headers["svix-timestamp"],
"svix-signature": req.headers["svix-signature"],
}); // throws on bad signature or stale timestampfrom svix.webhooks import Webhook # pip install svix
wh = Webhook(os.environ["MEMES_WEBHOOK_SECRET"]) # whsec_…
event = wh.verify(raw_body, {
"svix-id": headers["svix-id"],
"svix-timestamp": headers["svix-timestamp"],
"svix-signature": headers["svix-signature"],
}) # raises on bad signature or stale timestampTo verify manually: svix-signature is a space-separated list of v1,<base64> signatures, each HMAC-SHA256(secret, "{svix-id}.{svix-timestamp}.{raw_body}") over the base64 bytes after the whsec_ prefix; reject if |now − svix-timestamp| > 5 minutes. Deliveries are at-least-once — dedupe on svix-id. Failed deliveries retry with backoff for ~24h and are replayable from your webhook portal.
Managing endpoints
curl https://api.memes.media/v1/webhooks \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/hooks/memes",
"events": ["generation.completed", "generation.failed"]
}'Images
Generate and edit ad images from a prompt, a brand context, and up to four reference images.
Create an image
POST /images
| Param | Type | Description | |
|---|---|---|---|
prompt | string | one of* | Creative direction. |
brand_kit_id | string | one of* | A saved brand kit to ground the image. |
brand_context | object | one of* | Inline brand profile if you have no kit. |
reference_images | array | optional | Up to 4 { type, source }; type is ref/template/logo, source is an https URL or asset id. |
aspect_ratio | enum | optional | auto, 1:1 (default), 4:5, 3:4, 16:9, 9:16, 2:3, 3:2, 21:9, … |
count | integer | optional | Variants, 1–4. Default 1. |
quality | enum | optional | fast, standard (default), premium. |
model | enum | optional | forge-image (default) or forge-image-fast. |
* At least one of prompt, brand_kit_id/brand_context, or reference_images.
Reuse outputs as inputs. Any output[].id (asset_…) from a previous generation can be passed as a reference_images[].source, an image_id for edits/reframes, or to animate — so you can iterate without re-uploading.
curl https://api.memes.media/v1/images \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "Minimalist product hero on a sunlit kitchen counter",
"brand_kit_id": "bk_dawn_roasters",
"reference_images": [{ "type": "logo", "source": "https://yourcdn.example/logo.png" }],
"aspect_ratio": "4:5",
"count": 3
}'Returns 202 with a Generation (type: "image"). Credits: 1 per delivered image.
Edit & reframe
POST /images/edits applies a natural-language instruction (≤2000 chars) to an image_id, optionally within a mask (a PNG data: URL) for inpainting. POST /images/reframe outpaints an image_id into a new aspect_ratio. Both return 202; the new asset's parent_id points to the source. Credits: 1 each.
Memes
Memes are the flagship branded-ad format: a brand-grounded image with full edit/reframe lineage. Functionally they're Images with meme defaults plus lineage fields.
Create memes
| Param | Type | Description | |
|---|---|---|---|
prompt | string | one of* | The joke, angle, or message. |
brand_kit_id / brand_context | string / object | one of* | Brand grounding. |
template_prompt | string | optional | A meme-template directive to anchor the format. |
reference_images | array | optional | Up to 4 typed references. |
aspect_ratio | enum | optional | Default 1:1. |
count | integer | optional | 1–4. Default 1. |
enhance | boolean | optional | Run prompt enhancement first. |
* At least one of prompt, brand_kit_id/brand_context, or template_prompt.
curl https://api.memes.media/v1/memes \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "POV: you discover cold brew the night before a deadline",
"brand_kit_id": "bk_dawn_roasters",
"count": 4,
"enhance": true
}'Returns 202 (type: "meme"). Credits: 1 per delivered variant. GET /memes/{id}/lineage returns the root plus every edit and reframe in chronological order.
Videos
Generate short-form video from text, references, or an existing image.
Create a video
| Param | Type | Description | |
|---|---|---|---|
prompt | string | one of* | What the video shows. |
business_url | string | one of* | A website to ground the concept. |
brand_kit_id / brand_context | string / object | one of* | Brand grounding. |
reference_images | array | optional | Up to 4; their presence routes to reference-to-video. |
aspect_ratio | enum | optional | 16:9 (default), 9:16, 1:1, 4:3, 3:4, … |
duration | integer | optional | Seconds, 1–15. Default 5. |
resolution | enum | optional | 480p or 720p (default). |
The model (forge-video or forge-motion) is selected automatically from your inputs.
curl https://api.memes.media/v1/videos \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"prompt": "A latte poured in slow motion, steam rising, warm morning light",
"brand_kit_id": "bk_dawn_roasters",
"aspect_ratio": "9:16",
"duration": 6
}'Returns 202 (type: "video"). Credits: 10 per completed video. Video takes 1–4 minutes — use a webhook. POST /videos/animate takes an image_id and runs at 5s / 720p with forge-motion.
Carousels
Two steps by design: a free strategy plan, then a billable render that fans out one image per slide.
Plan a carousel
| Param | Type | Description | |
|---|---|---|---|
brief | string | required | What the carousel should accomplish, ≤2500 chars. |
goal | enum | optional | awareness, leads (default), sales, followers, engagement. |
platform | enum | optional | ig-portrait, ig-square, linkedin, tiktok. |
slide_count | integer | optional | 3–10. Default 5. |
brand_kit_id / brand_context | string / object | optional | Brand grounding. |
curl https://api.memes.media/v1/carousels/plan \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"brief": "5 myths about cold brew, debunked, for first-time buyers",
"goal": "leads",
"platform": "ig-portrait",
"slide_count": 5,
"brand_kit_id": "bk_dawn_roasters"
}'{
"plan": {
"id": "plan_71kd",
"concept_title": "Cold Brew Myths, Busted",
"viral_mechanic": "myth/fact reveal",
"cta": "Try the starter kit",
"slides": [
{ "slide_index": 0, "role": "hook", "on_image_text": "5 cold brew myths" }
]
},
"model": "forge-plan"
}Planning returns 200 synchronously (it's free). To render, POST /carousels with a plan_id (or inline plan) — it returns 202 (type: "carousel") and slides stream into output[] as they complete. Credits: 1 × slide_count.
Storyboards
A storyboard is a single composite 3–4 panel narrative ad image (not a fan-out).
| Param | Type | Description | |
|---|---|---|---|
goal | string | one of* | What the story should land. |
brand_kit_id / brand_context | string / object | one of* | Brand grounding. |
preset | enum | optional | auto, problem-solution, before-after, how-it-works, customer-journey, testimonial-sequence, founder-story. |
panel_count | integer | optional | 3 or 4. Default 3. |
aspect_ratio | enum | optional | 16:9, 9:16, 1:1. |
visual_style | enum | optional | comic-strip or clean-storyboard. |
tone | enum | optional | Narrative tone, e.g. playful, bold, warm, professional. |
text_density | enum | optional | minimal, balanced, rich. |
product_role | enum | optional | How prominently the product features. |
reference_images | array | optional | Up to 4 typed references. |
* At least one of goal or brand_kit_id / brand_context.
curl https://api.memes.media/v1/storyboards \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"goal": "Show how cold brew goes from beans to glass in 3 steps",
"brand_kit_id": "bk_dawn_roasters",
"preset": "how-it-works",
"panel_count": 3
}'Returns 202 (type: "storyboard"). Credits: 4.
Brand Kits
Reusable brand profiles — logo, colors, voice, audience, products — that ground any generation. Free and unlimited on every plan.
Create a brand kit
| Param | Type | Description | |
|---|---|---|---|
name | string | required | A label for the kit. |
company_name | string | optional | Brand name. |
website_url | string | optional | Brand site. |
brand_colors | string[] | optional | Hex colors. |
tone_of_voice | string | optional | Voice description. |
target_audience | string | optional | Audience description. |
website_context | string | optional | Positioning notes. |
industry | string | optional | Industry. |
auto_attach_product_references | boolean | optional | Auto-pull product images from the site. Default true. |
curl https://api.memes.media/v1/brand-kits \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Dawn Roasters",
"company_name": "Dawn Roasters",
"website_url": "https://dawnroasters.example",
"brand_colors": ["#3B2A1A", "#E8C39E"],
"tone_of_voice": "warm, witty, unpretentious"
}'{
"brand_kit": {
"id": "bk_dawn_roasters",
"object": "brand_kit",
"name": "Dawn Roasters",
"is_default": false,
"created_at": "2026-06-18T17:00:00Z"
}
}The returned id is what you pass as brand_kit_id everywhere else. POST /brand-kits/analyze-url with { "url": "https://…" } returns an extracted profile without saving it — great for pre-filling. Synchronous 200.
Prompt Enhancement
Turn a rough idea into a polished, production-ready creative prompt.
curl https://api.memes.media/v1/prompts/enhance \
-H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{ "prompt": "funny ad about mondays and coffee", "website_url": "https://dawnroasters.example" }'{
"enhanced_prompt": "A weary office worker slumped at a desk Monday morning, transformed mid-sip...",
"original_prompt": "funny ad about mondays and coffee",
"model": "forge-prompt"
}Synchronous 200. Pass has_logo, has_reference_image, and aspect_ratio to tailor the result to your intended render.
Images as inputs
You don't upload files to use an image as a reference, mask, or edit source — pass an https URL or a workspace asset id and the API fetches and normalizes it server-side. A source (in reference_images[]) or an image_id/mask accepts:
https URL | Your own hosted asset URL, or any public image URL. |
| workspace asset id | Any asset_… from a previous generation's output[] (or a meme/image id you own) — feed a generated image straight back in, no re-upload. |
"reference_images": [
{ "type": "logo", "source": "https://yourcdn.example/logo.png" },
{ "type": "ref", "source": "asset_5Tk8wQ" }
]Presigned uploads (POST /files) for raw local bytes are coming soon. Until then, host the image and pass its URL — every input path already fetches and normalizes URLs for you.
Account & Usage
Read your workspace's plan and current consumption.
curl https://api.memes.media/v1/account/usage \
-H "Authorization: Bearer sk_live_YOUR_KEY"{
"plan": "pro",
"credits_remaining": 480,
"intervals": {
"images": { "limit": 1000, "used": 520, "remaining": 480, "interval": "rolling_30_days", "reset_at": "2026-07-01T00:00:00Z" },
"video": { "limit": 50, "used": 4, "remaining": 46, "interval": "rolling_30_days", "reset_at": "2026-07-01T00:00:00Z" }
}
}SDKs & MCP
TypeScript & Python SDKs soon
Typed clients with automatic retries, idempotency, and a webhook-signature helper.
MCP server soon
Every operation as a Model Context Protocol tool — generate_meme, generate_video, plan_carousel, get_generation — so agents can build campaigns directly.
Until the SDKs ship, the API is plain REST — any HTTP client works. Want early access to a key, an SDK, or the MCP server? Email members@memes.com.
Cookbook
Real things you can build with the API — point your Shopify, Google Sheet, or Notion catalog at it, spin up Meta creative tests, animate Reels. Pick a card for the exact setup. These are starting points for inspiration, not a limit — building something or have a wild integration in mind? We'd love to help or just hear about it: members@memes.com. Also as plain Markdown.