# Supermeme.ai Meme API Generate finished memes, editable captions with blank templates, or minimalist illustrations from text. - Base URL: `https://app.supermeme.ai` - Documentation: https://supermeme.ai/meme-api/docs - Published OpenAPI 3.1 contract: https://app.supermeme.ai/openapi.json - Interactive reference: https://app.supermeme.ai/swagger - API key and current allowance: https://supermeme.ai/account/developers - Plans: https://supermeme.ai/pricing - Installable REST skill: https://supermeme.ai/skills/supermeme/SKILL.md - Assistant connection: https://supermeme.ai/mcp (client eligibility and OAuth setup) Updated on 4 October 2026 against the published OpenAPI contract. Response examples are illustrative; `example.invalid` URLs are placeholders. ## Authentication An active paid plan is required. Keep your key on the server in `SUPERMEME_API_KEY`. Send it on all four product endpoints: ```text Authorization: Bearer YOUR_API_KEY ``` Generate or replace the key in the developer dashboard. Replacing a key invalidates the previous key; update your integration to use the replacement. Keep real keys out of browser code, logs and public repositories. ## Example request: one finished meme ```bash curl --fail-with-body --max-time 120 \ -X POST https://app.supermeme.ai/api/v2/meme/image \ -H "Authorization: Bearer $SUPERMEME_API_KEY" \ -H "Content-Type: application/json" \ -d '{"text":"When the tests finally pass","count":1}' ``` This example requires cURL 7.76 or newer. Running it uses account allowance. The 120-second timeout is a client setting, not a response-time guarantee. ## Endpoints ### POST /api/v2/meme/image: finished meme images Returns memes with captions already rendered. | Field | Type | Requirement | | --- | --- | --- | | `text` | string | Required; 1–2,500 characters | | `count` | number | Optional; below 1 is rejected, decimals are truncated, values above 12 are capped. Set explicitly for a particular batch size. | | `aspectRatio` | string | Optional; `1:1`, `3:4`, `4:3`, `9:16` or `16:9` | | `paddingColor` | string | Optional; `#` plus 3 or 6 uppercase hexadecimal characters, such as `#FFF` or `#FFFFFF`. Default `#FFFFFF`. | Illustrative 200 response: ```json { "memes": ["https://example.invalid/generated-meme.png"], "expiresAt": "2026-10-04T13:00:00.000Z" } ``` Both `memes` and `expiresAt` are required. Signed image URLs last one hour. Download the image bytes before `expiresAt` and save them in your own storage if needed later. Saving only the URL does not preserve the image. `POST /api/v1/meme/image` remains an alias. ### POST /api/v1/minimalist-visual: illustrations | Field | Type | Requirement | | --- | --- | --- | | `text` | string | Required; 1–2,500 characters | | `count` | number | Optional; 1–3, default 1 | | `aspectRatio` | string | Optional; the same five ratios as finished memes, default `1:1` | Illustrative 200 response: ```json { "images": ["https://example.invalid/minimalist-visual.png"], "expiresAt": "2026-10-04T13:00:00.000Z" } ``` Both `images` and `expiresAt` are required. Save the image bytes before the signed one-hour URLs expire. ### POST /api/v1/meme/text: editable captions and templates Send `{"text":"When the tests finally pass"}`. Required `text` accepts 1–2,500 characters. Captions and public blank-template URLs come back separately for your application to offer a choice or render. Illustrative 200 response: ```json { "memes": [ { "caption": "When the tests finally pass", "image": "https://example.invalid/blank-template.png" } ], "searchEmotion": "relief", "originalText": "When the tests finally pass", "generatedCaptions": ["When the tests finally pass"], "languageCode": "English" } ``` All five top-level fields are required. Each meme requires `caption` and `image`. `languageCode` reports the detected input language. Check that the returned captions use the language you intended, and review their wording before publishing. Blank-template URLs are public, rather than signed generated-image URLs; this response has no `expiresAt`. ### GET /api/v1/search: blank templates Send a non-empty, URL-encoded `query`, such as `/api/v1/search?query=confused`. Illustrative 200 response: ```json { "templates": [ "https://example.invalid/blank-template-1.png", "https://example.invalid/blank-template-2.png" ] } ``` The required `templates` array contains up to 20 public blank-template URLs. Use the URLs directly; do not prepend a guessed storage path or depend on stable result order. ## Quotas and response headers Check your actual billing-period allowance and usage in the developer dashboard. Do not assume a failed or timed-out generation consumed no quota. The current OpenAPI contract documents these headers on 200 and 429 responses for all four product endpoints: | Header | Meaning | | --- | --- | | `X-RateLimit-Limit` | Billing-period request allowance | | `X-RateLimit-Remaining` | Conservative remaining count; treat 0 as a stop signal | | `X-RateLimit-Reset` | Reset time as a Unix timestamp in seconds | Read headers when present. If missing, consult the dashboard; missing headers do not mean unlimited quota. HTTP 429 with `type: quota_exceeded` means stop and wait for the billing-period reset. ## Errors and retries The four endpoints document 400, 401, 403, 429 and 500 error responses. Required fields are `status`, `type`, `message` and `timestamp`; `correlationId` and extra `error` details are optional. Illustrative quota error: ```json { "status": 429, "type": "quota_exceeded", "message": "You have reached your API limit", "timestamp": "2026-10-04T12:00:00.000Z" } ``` | HTTP | Type | Next step | | --- | --- | --- | | 400 | `validation_error` | Correct missing or invalid input. | | 401 | `unauthorized` | Check the bearer token and current key. | | 403 | `forbidden` | Check paid-plan access in the dashboard. | | 429 | `quota_exceeded` | Wait for the reset or arrange more allowance. | | 500 | `internal_error` | Preserve the error and any correlation ID before deciding whether to retry. | The error schema also includes `not_found`, `conflict` and `service_unavailable`; these are not separately listed as endpoint response statuses in the current contract. Use bounded client timeouts and avoid overlapping generation requests. No idempotency key is documented. A timeout or 5xx response does not prove a generation was never processed: repeating a POST may create another batch and consume quota again. Decide how your application handles that uncertainty before adding automatic retries. ## Connection check Public `GET https://app.supermeme.ai/health` returns `{"message":"OK"}` when the service responds. It does not verify your key, paid-plan access, quota or a complete generation.