Errors
Every non-2xx response from the API returns the same envelope:
JSON
{
"error": {
"code": "invalid_category",
"message": "Unknown category 'women-kurti'. Use GET /api/v1/categories to browse.",
"correlation_id": "0192a8d4-...",
"docs_url": "https://meeship.in/for-integrations/docs/errors",
"suggestions": ["womens-kurtis", "mens-kurtis"],
"retry_after_seconds": 30
}
}Where:
codeis a stable, machine-readable string. Pin your error handling
to code, not the HTTP status (some codes share a status).
messageis human-readable. Never contains internal IDs or stack traces.correlation_iduniquely identifies the request. Include it in support
tickets — it's also returned as the X-Correlation-Id header.
docs_url,suggestions,retry_after_secondsare optional; present
only when relevant.
Code reference#
Authentication & authorization#
| Status | Code | When | Fix |
|---|---|---|---|
| 401 | unauthorized | Missing or non-Bearer Authorization header. | Send Authorization: Bearer meeship_<token>. |
| 401 | invalid_api_key | Unknown / revoked / wrong-format token. | Generate a fresh key from the dashboard. |
| 402 | subscription_expired | Subscription is cancelled or past grace period. | Buy another credit pack. |
| 403 | ip_not_allowed | Caller IP isn't in this key's allowlist. | Update the allowlist or use a key without one. |
Quota & rate limits#
| Status | Code | When | Fix |
|---|---|---|---|
| 402 | quota_exhausted | Credit balance is 0. | Buy another pack. |
| 429 | rate_limited | Exceeded per-minute submit (or polling) cap. | Wait Retry-After seconds; back off polling. |
Input validation#
| Status | Code | When | Fix |
|---|---|---|---|
| 400 | missing_image | Empty image part. | Upload a real image file. |
| 400 | invalid_image | Unsupported format, decoding failed, or below 400×400 px. | Use JPEG/PNG/WebP at ≥ 400×400 px. |
| 413 | image_too_large | Image exceeds 10 MB. | Resize / re-encode before upload. |
| 400 | invalid_category | Slug/id not in catalogue. Response includes suggestions. | Use one of the suggested slugs, or GET /api/v1/categories?search=…. |
Jobs#
| Status | Code | When | Fix |
|---|---|---|---|
| 404 | job_not_found | Unknown job_id or not owned by your subscription. | Check the id; ensure you're using the same API key. |
Server / upstream#
| Status | Code | When | Fix |
|---|---|---|---|
| 500 | internal_error | Unexpected MeeShip-side fault. | Retry; include correlation_id if it persists. |
| 502 | upstream_unavailable | Meesho shipping API returned no valid data. | The job ends in failed with no credit charged. Retry safely. |
| 502 | razorpay_error | (billing endpoints only) Razorpay API call failed. | Retry; check the dashboard for partial state. |
Retrying safely#
All 4xxs except 429 are client errors — retrying won't help unless you change the request. 429 always returns Retry-After; respect it. 5xxs are safe to retry with exponential backoff — and because credits are only charged when a job reaches complete, you'll never be billed twice.
For POST /optimizations, set an Idempotency-Key header (any client-chosen string, max 255 chars). Repeated submits with the same key within 24 hours return the same job_id — perfect for retrying after a network blip without enqueueing a duplicate job.