Optimizations
The primary workflow: submit a product image, then poll for the shipping-optimized results.
Try it
Run a real call against POST /api/v1/optimizations. Your key is kept in sessionStorage only — never persisted, never sent to our backend except as the request's Bearer token.
POST /api/v1/optimizations#
Submit a new optimization job. Returns 202 Accepted within ~2 seconds with a job_id you can poll.
Authentication: required (Authorization: Bearer meeship_<token>).
Request — multipart/form-data#
| Field | Type | Required | Notes |
|---|---|---|---|
image | file | yes | jpeg/png/webp, ≤ 10 MB, min 400×400 px, ≤ 50 MP. |
category | string | yes | Slug (e.g. womens-kurtis). Discover slugs via GET /api/v1/categories. |
selling_price_inr | integer | no | Defaults to 299. Used for the transfer-price calculation. |
Request headers#
| Header | Purpose |
|---|---|
Authorization | Bearer meeship_<token> |
Idempotency-Key | Optional. Any client-chosen string (max 255). Same key within 24h → same job_id. |
Response — 202 Accepted#
{
"job_id": "8d7e9b3c-1f4a-4d2e-9f50-aabbccdd1122",
"status": "queued",
"status_url": "https://api.meeship.in/api/v1/jobs/8d7e...",
"submitted_at": "2026-05-26T11:42:03Z",
"category": {
"slug": "womens-kurtis",
"name": "Women Kurtis",
"breadcrumb": "Women Ethnic > Kurtis"
}
}Response headers: X-Correlation-Id, X-Credits-Remaining.
Error codes#
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_image | Bad format, decoding failed, or below the 400×400 min dimension. |
| 400 | missing_image | Image part was empty. |
| 400 | invalid_category | Unknown slug/id. Response includes suggestions array (up to 5). |
| 401 | unauthorized / invalid_api_key | Missing or revoked key. |
| 402 | quota_exhausted | Credit balance is 0. Buy a pack or upgrade. |
| 402 | subscription_expired | Subscription is cancelled or past grace period. |
| 403 | ip_not_allowed | Caller's source IP isn't in this key's allowlist. |
| 413 | image_too_large | Image exceeds 10 MB. |
| 429 | rate_limited | Exceeded your tier's per-minute submit limit. Response includes Retry-After header. |
GET /api/v1/jobs/{job_id}#
Poll a job. Returns the current state and, when terminal, the full result.
Authentication: required. Tenant-scoped — a foreign job_id returns 404, not 403 (we don't leak the existence of other tenants' jobs).
Response — 200 OK#
When status is queued or processing:
{
"job_id": "8d7e...",
"status": "processing",
"submitted_at": "2026-05-26T11:42:03Z",
"processing_started_at": "2026-05-26T11:42:09Z",
"category": { "slug": "womens-kurtis" },
"credits_charged": 0
}Response header Retry-After: 5 suggests how long to wait before the next poll.
When status is complete:
{
"job_id": "8d7e...",
"status": "complete",
"submitted_at": "2026-05-26T11:42:03Z",
"completed_at": "2026-05-26T11:43:18Z",
"expires_at": "2026-05-27T11:42:03Z",
"category": { "slug": "womens-kurtis" },
"credits_charged": 1,
"result": {
"baseline_shipping_charges_inr": 82,
"variants": [
{
"rank": 1,
"image_url": "https://blob.meeship.in/...",
"shipping_charges_inr": 55
}
]
}
}> ⚠️ Image URLs expire after 24 hours. Each image_url is a signed, > read-only link to Azure Blob Storage and stops resolving at the time > shown in expires_at (24h after completed_at). Download the bytes > within that window and store them in your own system if you need them > longer — re-polling GET /jobs/{id} after expiry returns the same URLs, > which will return 403 from storage.
When status is failed:
{
"job_id": "8d7e...",
"status": "failed",
"credits_charged": 0,
"error": {
"code": "upstream_unavailable",
"message": "Meesho shipping API returned no valid variants.",
"retryable": false
}
}Job lifecycle#
queued ──► processing ──┬──► complete (credits_charged = 1)
└──► failed (credits_charged = 0)
↓
expired (24h after complete; image URLs stop resolving)expires_at in the response is the hard deadline for image_url freshness. The job_id itself remains queryable for longer (we periodically garbage-collect), but the image URLs become unusable after expires_at — download the bytes before then.
Polling rate#
Polling is free (no credits charged) and has a separate, generous rate limit (10× your submit limit). Respect Retry-After; aggressive polling returns 429.
Snippets#
Python (requests)#
import time, requests
API = "https://api.meeship.in/api/v1"
KEY = "meeship_live_..."
# Submit
with open("product.jpg", "rb") as f:
r = requests.post(
f"{API}/optimizations",
headers={"Authorization": f"Bearer {KEY}",
"Idempotency-Key": "sku-12345"},
files={"image": f},
data={"category": "womens-kurtis", "selling_price_inr": 499},
)
r.raise_for_status()
job_id = r.json()["job_id"]
# Poll
while True:
r = requests.get(f"{API}/jobs/{job_id}",
headers={"Authorization": f"Bearer {KEY}"})
r.raise_for_status()
job = r.json()
if job["status"] in ("complete", "failed", "expired"):
break
time.sleep(int(r.headers.get("Retry-After", "5")))
if job["status"] == "complete":
for v in job["result"]["variants"]:
print(v["rank"], v["image_url"], v["shipping_charges_inr"])JavaScript (fetch)#
const API = 'https://api.meeship.in/api/v1';
const KEY = 'meeship_live_...';
async function optimize(file, category) {
const fd = new FormData();
fd.append('image', file);
fd.append('category', category);
const submit = await fetch(`${API}/optimizations`, {
method: 'POST',
headers: {
Authorization: `Bearer ${KEY}`,
'Idempotency-Key': crypto.randomUUID(),
},
body: fd,
});
if (!submit.ok) throw new Error(await submit.text());
const { job_id } = await submit.json();
while (true) {
const r = await fetch(`${API}/jobs/${job_id}`, {
headers: { Authorization: `Bearer ${KEY}` },
});
const job = await r.json();
if (['complete', 'failed', 'expired'].includes(job.status)) return job;
await new Promise((s) => setTimeout(s, +(r.headers.get('Retry-After') || 5) * 1000));
}
}curl#
# Submit
curl -X POST https://api.meeship.in/api/v1/optimizations \
-H "Authorization: Bearer meeship_live_..." \
-H "Idempotency-Key: sku-12345" \
-F image=@./product.jpg \
-F category=womens-kurtis \
-F selling_price_inr=499
# Poll (replace JOB_ID with the value above)
curl -H "Authorization: Bearer meeship_live_..." \
https://api.meeship.in/api/v1/jobs/JOB_ID