Errors
Error codes, HTTP statuses, and how to handle them.
Envelope
Every error follows this shape:
{
"success": false,
"error": {
"code": "INSUFFICIENT_CREDITS",
"message": "You have 0 credits remaining. Please upgrade your plan.",
"doc_url": "https://docs.createa.meme/docs/errors#codes"
}
}Codes
| Code | HTTP | Meaning |
|---|---|---|
INVALID_API_KEY | 401 | Key doesn't exist or is revoked |
EXPIRED_API_KEY | 401 | Key has passed its expiration date |
SUSPENDED_API_KEY | 403 | Key suspended for abuse or non-payment |
RATE_LIMITED | 429 | Too many requests per minute |
INSUFFICIENT_CREDITS | 402 | Not enough credits for this operation |
VALIDATION_ERROR | 400 | Request body failed schema validation |
TEMPLATE_NOT_FOUND | 404 | Template ID doesn't exist |
JOB_NOT_FOUND | 404 | Async job ID doesn't exist |
GENERATION_FAILED | 500 | AI model returned an error (an outage or bad output — content refusals are NSFW_REJECTED) |
MODEL_UNAVAILABLE | 503 | Requested AI model is temporarily down |
NSFW_REJECTED | 422 | Content was refused — by our moderation filter or by the image model's own safety system. See Content refusals |
Content refusals
POST /v1/meme/ai-image and POST /v1/meme/remix pass through two safety layers: our
moderation filter checks your prompt first, then the image model applies its own policy. Either
refusal returns 422 NSFW_REJECTED with extra fields that tell you which layer said no:
{
"success": false,
"error": {
"code": "NSFW_REJECTED",
"message": "The gpt-image-2 model's safety system declined this request (sexual). Retrying the same prompt won't help — rephrase it (for example, add scene context) or try a different model.",
"refused_by": "model",
"model": "gpt-image-2",
"categories": ["sexual"],
"retryable": false,
"doc_url": "https://docs.createa.meme/docs/errors#codes"
}
}| Field | Meaning |
|---|---|
refused_by | "platform" — our moderation filter; it applies to every model, so rephrase the prompt. "model" — that model's own policy; a rephrase or a different model can succeed |
model | The model that refused (present when refused_by is "model") |
categories | Policy categories, when the refusing layer reports them (can be empty) |
retryable | Always false: resending the identical request gets the same refusal |
Refused requests are never charged — credits are refunded automatically. Models don't all draw
the line in the same place, and wording matters: grok checks the finished image and has refused
every swimwear prompt we've tried, while in our tests gpt-image-2 accepted "a woman in a swimsuit
at the beach" but refused "a pretty woman in a swimsuit".