{"openapi":"3.0.3","info":{"title":"Memegen.link","version":"11.2","description":"\n## Quickstart\n\nFetch the list of templates:\n\n```\n$ http GET https://api.memegen.link/templates\n\n[\n    {\n        \"id\": \"aag\",\n        \"name\": \"Ancient Aliens Guy\",\n        \"lines\": 2,\n        \"overlays\": 0,\n        \"source\": \"http://knowyourmeme.com/memes/ancient-aliens\",\n        ...\n    },\n    ...\n]\n```\n\nAdd text to create a meme:\n\n```\n$ http POST https://api.memegen.link/images template_id=aag \"text[]=foo\" \"text[]=bar\"\n\n{\n    \"url\": \"https://api.memegen.link/images/aag/foo/bar.png\"\n}\n```\n\nView the image: <https://api.memegen.link/images/aag/foo/bar.png>\n\n## Links\n","license":{"name":"View the license","url":"https://github.com/jacebrowning/memegen/blob/main/LICENSE.txt"},"contact":{"name":"support","email":"support@maketested.com"}},"paths":{"/images/preview.jpg":{"get":{"operationId":"get~Clients.preview","summary":"Display a preview of a custom meme","tags":["Clients"],"parameters":[{"name":"layout","schema":{"type":"string"},"description":"Text position: `default` or `top`","in":"query"},{"name":"template","schema":{"type":"string"},"description":"Template ID, URL, or custom background","in":"query"},{"name":"style","schema":{"type":"string"},"description":"Style name or custom overlay","in":"query"},{"name":"text[]","schema":{"type":"string"},"description":"Lines of text to render","in":"query"}],"responses":{"200":{"content":{"image/jpeg":{"schema":{"type":"string","format":"byte"}}},"description":"Successfully displayed a custom meme"}}}},"/auth":{"post":{"operationId":"post~Clients.validate","summary":"Validate your API key","tags":["Clients"],"responses":{"401":{"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","title":"Error"}}}}},"description":"Your API key is invalid"},"200":{"content":{"application/json":{"schema":{"type":"object","properties":{"email":{"type":"string","title":"Email"},"image_access":{"type":"boolean","title":"Image_Access"},"search_access":{"type":"boolean","title":"Search_Access"},"created":{"type":"string","format":"date-time","title":"Created"},"modified":{"type":"string","format":"date-time","title":"Modified"}}}}},"description":"Your API key is valid"}}}},"/fonts":{"get":{"operationId":"get~Fonts.index","summary":"List available fonts","tags":["Fonts"],"responses":{"200":{"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"filename":{"type":"string","title":"Filename"},"id":{"type":"string","title":"Id"},"alias":{"type":"string","title":"Alias"}}}}}},"description":"Successfully returned a list of fonts"}},"description":"\nFonts available for the `font=` query parameter on path-based image\nendpoints. Each entry has an `id` and an optional `alias`.\n"}},"/images":{"post":{"operationId":"post~Images.create","summary":"Create a meme from a template","tags":["Images"],"responses":{"404":{"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","title":"Error"}}}}},"description":"Specified \"template_id\" does not exist"},"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","title":"Error"}}}}},"description":"Required \"template_id\" missing in request body"},"201":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","title":"Url"}}}}},"description":"Successfully created a meme"}},"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"template_id":{"type":"string","title":"Template_Id"},"style":{"type":"array","items":{"type":"string"},"title":"Style"},"text":{"type":"array","items":{"type":"string"},"title":"Text"},"layout":{"type":"string","title":"Layout"},"font":{"type":"string","title":"Font"},"extension":{"type":"string","title":"Extension"},"redirect":{"type":"boolean","title":"Redirect"}}}}}},"description":"\nCreate a meme by `POST`ing raw text. The response includes a canonical\n`url` field with path escaping applied \u2014 prefer this over hand-built\n`GET` URLs when text contains spaces or reserved characters.\n\nBody fields:\n- `template_id`: Template to render (`GET /templates/`).\n- `text`: Lines of text in order (raw, not escape-encoded). Up to the\n  template's `lines` value; pass an empty string for an empty intermediate\n  line.\n- `style`: Style names from the template's `styles` field, or HTTPS URLs\n  for custom overlay images. When `overlays` > 1, the array sets each slot.\n- `extension`: Output image extension.\n- `redirect`: If true, returns 302 to the canonical URL instead of JSON.\n"},"get":{"operationId":"get~Images.index","summary":"List example memes","tags":["Images"],"parameters":[{"name":"filter","schema":{"type":"string"},"description":"Part of the template name or example to match","in":"query"}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","title":"Url"},"template":{"type":"string","title":"Template"}}}}}},"description":"Successfully returned a list of example memes"}}}},"/images/automatic":{"post":{"operationId":"post~Images.create_automatic","summary":"Create a meme from word or phrase","tags":["Images"],"responses":{"400":{"content":{"application/json":{"schema":{"type":"object","properties":{"error":{"type":"string","title":"Error"}}}}},"description":"Required \"text\" missing in request body"},"201":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","title":"Url"}}}}},"description":"Successfully created a meme"}},"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"text":{"type":"string","title":"Text"},"safe":{"type":"boolean","title":"Safe"},"redirect":{"type":"boolean","title":"Redirect"}}}}}}}},"/images/custom":{"post":{"operationId":"post~Images.create_custom","summary":"Create a meme from any image","tags":["Images"],"responses":{"201":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","title":"Url"}}}}},"description":"Successfully created a meme from a custom image"}},"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"background":{"type":"string","title":"Background"},"style":{"type":"string","title":"Style"},"text":{"type":"array","items":{"type":"string"},"title":"Text"},"layout":{"type":"string","title":"Layout"},"font":{"type":"string","title":"Font"},"extension":{"type":"string","title":"Extension"},"redirect":{"type":"boolean","title":"Redirect"}}}}}}},"get":{"operationId":"get~Images.index_custom","summary":"List popular custom memes","tags":["Images"],"parameters":[{"name":"filter","schema":{"type":"string"},"description":"Part of the meme's text to match","in":"query"},{"name":"safe","schema":{"type":"boolean"},"description":"Exclude NSFW results","in":"query"}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string","title":"Url"}}}}}},"description":"Successfully returned a list of custom memes"}}}},"/templates":{"get":{"operationId":"get~Templates.index","summary":"List all templates","tags":["Templates"],"parameters":[{"name":"filter","schema":{"type":"string"},"description":"Part of the name, keyword, or example to match","in":"query"},{"name":"animated","schema":{"type":"boolean"},"description":"Limit results to templates supporting animation","in":"query"}],"responses":{"200":{"content":{"application/json":{"schema":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"lines":{"type":"integer","format":"int32","title":"Lines"},"overlays":{"type":"integer","format":"int32","title":"Overlays"},"styles":{"type":"array","items":{"type":"string"},"title":"Styles"},"blank":{"type":"string","title":"Blank"},"example":{"type":"object","title":"Example","properties":{"text":{"type":"array","items":{"type":"string"},"title":"Text"},"url":{"type":"string","title":"Url"}}},"source":{"type":"string","title":"Source"}}}}}},"description":"Successfully returned a list of all templates"}},"description":"\nThe full list of renderable templates. For URL construction, the four\nload-bearing fields per template are `id` (goes into the path after\n`/images/`), `lines` (maximum number of `/`-separated text segments\naccepted in the path), `overlays` (number of overlay image slots the\ntemplate defines), and `styles` (allowed values for the `style=` query\nparameter). The remaining fields are descriptive: `name` for display,\n`blank` for the empty-template render URL, `example.url` for a\nguaranteed-valid smoke-test URL, `source` for attribution, and\n`keywords` for search. Recommended client pattern: fetch this endpoint\nonce at startup, cache, and construct URLs locally rather than per-meme.\n"}},"/templates/custom":{"post":{"operationId":"post~Templates.custom","summary":"Create a meme from any image","tags":["Templates"],"responses":{"201":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","title":"Url"}}}}},"description":"Successfully created a meme from a custom image"}},"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"background":{"type":"string","title":"Background"},"style":{"type":"string","title":"Style"},"text":{"type":"array","items":{"type":"string"},"title":"Text"},"layout":{"type":"string","title":"Layout"},"font":{"type":"string","title":"Font"},"extension":{"type":"string","title":"Extension"},"redirect":{"type":"boolean","title":"Redirect"}}}}}}}},"/fonts/{id}":{"get":{"operationId":"get~Fonts.detail","summary":"View a specific font","tags":["Fonts"],"parameters":[{"name":"id","schema":{"type":"string"},"description":"ID of a font","required":true,"in":"path"}],"responses":{"404":{"content":{"*/*":{"schema":{"type":"string"}}},"description":"Font not found"},"200":{"content":{"application/json":{"schema":{"type":"object","properties":{"filename":{"type":"string","title":"Filename"},"id":{"type":"string","title":"Id"},"alias":{"type":"string","title":"Alias"}}}}},"description":"Successfully returned a specific font"}}}},"/templates/{id}":{"post":{"operationId":"post~Templates.build","summary":"Create a meme from a template","tags":["Templates"],"parameters":[{"name":"id","schema":{"type":"string"},"description":"ID of a meme template","required":true,"in":"path"}],"responses":{"201":{"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","title":"Url"}}}}},"description":"Successfully created a meme from a template"}},"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"style":{"type":"array","items":{"type":"string"},"title":"Style"},"text":{"type":"array","items":{"type":"string"},"title":"Text"},"layout":{"type":"string","title":"Layout"},"font":{"type":"string","title":"Font"},"extension":{"type":"string","title":"Extension"},"redirect":{"type":"boolean","title":"Redirect"}}}}}}},"get":{"operationId":"get~Templates.detail","summary":"View a specific template","tags":["Templates"],"parameters":[{"name":"id","schema":{"type":"string"},"description":"ID of a meme template","required":true,"in":"path"}],"responses":{"404":{"content":{"*/*":{"schema":{"type":"string"}}},"description":"Template not found"},"200":{"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","title":"Id"},"name":{"type":"string","title":"Name"},"lines":{"type":"integer","format":"int32","title":"Lines"},"overlays":{"type":"integer","format":"int32","title":"Overlays"},"styles":{"type":"array","items":{"type":"string"},"title":"Styles"},"blank":{"type":"string","title":"Blank"},"example":{"type":"object","title":"Example","properties":{"text":{"type":"array","items":{"type":"string"},"title":"Text"},"url":{"type":"string","title":"Url"}}},"source":{"type":"string","title":"Source"}}}}},"description":"Successfully returned a specific template"}},"description":"\nPer-template metadata. The four URL-construction fields are `id`,\n`lines`, `overlays`, and `styles`; see `GET /templates/` for what each\none governs. The `example.url` field is a guaranteed-valid render URL \u2014\nissuing a `HEAD` against it is the cheapest way to validate that the\ntemplate id is live.\n"}},"/{template_id}":{"get":{"operationId":"get~Shortcuts.legacy_example_image","summary":"Redirect to an example image","tags":["Shortcuts"],"parameters":[{"name":"template_id","schema":{"type":"string"},"description":"ID of a meme template","required":true,"in":"path"}],"responses":{"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Template not found"},"302":{"content":{"image/*":{"schema":{"type":"string","format":"byte"}}},"description":"Successfully redirected to an example image"}}}},"/images/{template_id}/{text_filepath}":{"get":{"operationId":"get~Images.detail_text","summary":"Display a custom meme","tags":["Images"],"parameters":[{"name":"status","schema":{"type":"integer","format":"int32"},"description":"\nOverride the HTTP response status code. Primarily used internally by the\n`POST /images/` \u2192 redirect flow to propagate a `201 Created` semantic to the\nfinal image fetch. Most clients should not need to set this directly.\n","in":"query"},{"name":"frames","schema":{"type":"integer","format":"int32"},"description":"\nMaximum number of frames to render in animated output. 0 (default) means no\ncap. Use this to bound response size and render time on long animations.\n","in":"query"},{"name":"scale","schema":{"type":"number","format":"float"},"description":"\nMultiplier applied to the overlay's default size. Most useful with\n`style=<url>`.\n","in":"query"},{"name":"center","schema":{"type":"string"},"description":"\nComma-separated `<x>,<y>` fractional coordinates (0.0\u20131.0) for overlay center\nwithin its slot. Most useful with `style=<url>`.\n","in":"query"},{"name":"background","schema":{"type":"string"},"description":"\nCustom background image URL. Composes with `style=<url>` overlays.\n","in":"query"},{"name":"color","schema":{"type":"string"},"description":"\nComma-separated `<text>,<outline>` pair. Each value is an HTML color name\nor hex code (with or without a leading `#`).\n","in":"query"},{"name":"height","schema":{"type":"integer","format":"int32"},"description":"Output height in pixels. See `width` for combined behavior.","in":"query"},{"name":"width","schema":{"type":"integer","format":"int32"},"description":"\nOutput width in pixels. If both `width` and `height` are supplied, the image\nis padded to fit while preserving aspect ratio. Values between 1 and 9 are\nrejected with HTTP 422.\n","in":"query"},{"name":"layout","schema":{"type":"string"},"description":"\nText layout mode. Allowed values are defined by the API; `top` places all\ntext at the image top rather than the template's default regions.\n","in":"query"},{"name":"font","schema":{"type":"string"},"description":"\nFont `id` or `alias` overriding the template default (`GET /fonts/`).\nUnknown values return HTTP 422; the image still renders with the template\ndefault font.\n","in":"query"},{"name":"style","schema":{"type":"string"},"description":"\nAlternate visual variant from the template's `styles` array, OR an HTTPS\nURL to use as a custom overlay image. For templates with `overlays > 1`,\nmay be repeated to set each slot independently. Unknown style names return\nHTTP 422, not the default render.\n","in":"query"},{"name":"template_id","schema":{"type":"string"},"description":"ID of a meme template","required":true,"in":"path"},{"name":"text_filepath","schema":{"type":"string"},"description":"\nLines of text and output extension:\n`<line1>/<line2>/.../<line_n>.<extension>`, where `n` is at most the\ntemplate's `lines` value (`GET /templates/{id}`). Trailing lines may be\nomitted; pass `_` for an empty intermediate line. Path segments must be\nescape-encoded; prefer `POST /images/` with raw `text` and use the\ncanonical `url` from the response.\n","required":true,"in":"path"}],"responses":{"422":{"content":{"image/*":{"schema":{"type":"string","format":"byte"}}},"description":"Invalid style for template or no image URL specified for custom template"},"415":{"content":{"image/*":{"schema":{"type":"string","format":"byte"}}},"description":"Unable to download image URL"},"414":{"content":{"image/*":{"schema":{"type":"string","format":"byte"}}},"description":"Custom text too long (length >200)"},"404":{"content":{"image/*":{"schema":{"type":"string","format":"byte"}}},"description":"Template not found"},"200":{"content":{"image/*":{"schema":{"type":"string","format":"byte"}}},"description":"Successfully displayed a custom meme"}}}},"/images/{template_filename}":{"get":{"operationId":"get~Images.detail_blank","summary":"Display a template background","tags":["Images"],"parameters":[{"name":"status","schema":{"type":"integer","format":"int32"},"description":"\nOverride the HTTP response status code. Primarily used internally by the\n`POST /images/` \u2192 redirect flow to propagate a `201 Created` semantic to the\nfinal image fetch. Most clients should not need to set this directly.\n","in":"query"},{"name":"frames","schema":{"type":"integer","format":"int32"},"description":"\nMaximum number of frames to render in animated output. 0 (default) means no\ncap. Use this to bound response size and render time on long animations.\n","in":"query"},{"name":"scale","schema":{"type":"number","format":"float"},"description":"\nMultiplier applied to the overlay's default size. Most useful with\n`style=<url>`.\n","in":"query"},{"name":"center","schema":{"type":"string"},"description":"\nComma-separated `<x>,<y>` fractional coordinates (0.0 to 1.0) for overlay center\nwithin its slot. Most useful with `style=<url>`.\n","in":"query"},{"name":"background","schema":{"type":"string"},"description":"\nCustom background image URL. Composes with `style=<url>` overlays.\n","in":"query"},{"name":"color","schema":{"type":"string"},"description":"\nComma-separated `<text>,<outline>` pair. Each value is an HTML color name\nor hex code (with or without a leading `#`).\n","in":"query"},{"name":"height","schema":{"type":"integer","format":"int32"},"description":"Output height in pixels. See `width` for combined behavior.","in":"query"},{"name":"width","schema":{"type":"integer","format":"int32"},"description":"\nOutput width in pixels. If both `width` and `height` are supplied, the image\nis padded to fit while preserving aspect ratio. Values between 1 and 9 are\nrejected with HTTP 422.\n","in":"query"},{"name":"layout","schema":{"type":"string"},"description":"\nText layout mode. Allowed values are defined by the API; `top` places all\ntext at the image top rather than the template's default regions.\n","in":"query"},{"name":"font","schema":{"type":"string"},"description":"\nFont `id` or `alias` overriding the template default (`GET /fonts/`).\nUnknown values return HTTP 422; the image still renders with the template\ndefault font.\n","in":"query"},{"name":"style","schema":{"type":"string"},"description":"\nAlternate visual variant from the template's `styles` array, OR an HTTPS\nURL to use as a custom overlay image. For templates with `overlays > 1`,\nmay be repeated to set each slot independently. Unknown style names return\nHTTP 422, not the default render.\n","in":"query"},{"name":"template_filename","schema":{"type":"string"},"description":"\nTemplate ID and image format: `<template_id>.<extension>`. This is the\ncanonical empty-template render and matches the `blank` field on\n`GET /templates/{id}`. Use this when a client just wants the background.\nThe same query parameters as `/images/{template_id}/{text_filepath}`\napply.\n","required":true,"in":"path"}],"responses":{"422":{"content":{"image/*":{"schema":{"type":"string","format":"byte"}}},"description":"Invalid style for template or no image URL specified for custom template"},"415":{"content":{"image/*":{"schema":{"type":"string","format":"byte"}}},"description":"Unable to download image URL"},"404":{"content":{"image/*":{"schema":{"type":"string","format":"byte"}}},"description":"Template not found"},"200":{"content":{"image/*":{"schema":{"type":"string","format":"byte"}}},"description":"Successfully displayed a template background"}}}},"/images/{template_id}/{text_paths}":{"get":{"operationId":"get~Shortcuts.custom_path","summary":"Redirect to a custom image","tags":["Shortcuts"],"parameters":[{"name":"template_id","schema":{"type":"string"},"description":"ID of a meme template","required":true,"in":"path"},{"name":"text_paths","schema":{"type":"string"},"description":"Lines of text: `<line1>/<line2>`","required":true,"in":"path"}],"responses":{"302":{"content":{"image/*":{"schema":{"type":"string","format":"byte"}}},"description":"Successfully redirected to a custom image"}}}},"/images/{template_id}":{"get":{"operationId":"get~Shortcuts.example_path","summary":"Redirect to an example image","tags":["Shortcuts"],"parameters":[{"name":"template_id","schema":{"type":"string"},"description":"ID of a meme template","required":true,"in":"path"}],"responses":{"501":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Template not fully implemented"},"404":{"content":{"text/html":{"schema":{"type":"string"}}},"description":"Template not found"},"302":{"content":{"image/*":{"schema":{"type":"string","format":"byte"}}},"description":"Successfully redirected to an example image"}}}},"/{template_id}/{text_paths}":{"get":{"operationId":"get~Shortcuts.legacy_custom_path","summary":"Redirect to a custom image","tags":["Shortcuts"],"parameters":[{"name":"template_id","schema":{"type":"string"},"description":"ID of a meme template","required":true,"in":"path"},{"name":"text_paths","schema":{"type":"string"},"description":"Lines of text: `<line1>/<line2>`","required":true,"in":"path"}],"responses":{"302":{"content":{"image/*":{"schema":{"type":"string","format":"byte"}}},"description":"Successfully redirected to a custom image"}}}}},"tags":[{"name":"Clients"},{"name":"Fonts"},{"name":"Images"},{"name":"Templates"},{"name":"Shortcuts"}],"servers":[],"security":[{"ApiKeyAuth":[]}],"components":{"securitySchemes":{"ApiKeyAuth":{"type":"apiKey","name":"X-API-KEY","in":"header"}}},"externalDocs":{"url":"https://memegen.link/guide/","description":"Browse API guide"}}