Overview
A small, predictable REST API. Every response is JSON with camelCase keys; job creation is multipart/form-data so you can upload images directly.
Base URL
https://dodam.modawn.ai/api/v1Endpoints
- Method
- GET
- Endpoint
/rules- Scope
rules:read- Description
- Supported markets, or the rule set for a country + platform
- Method
- GET
- Endpoint
/usage- Scope
jobs:read- Description
- Monthly quota and units used
- Method
- GET
- Endpoint
/jobs- Scope
jobs:read- Description
- List inspections (cursor pagination)
- Method
- POST
- Endpoint
/jobs- Scope
jobs:write- Description
- Create an inspection from images + text (multipart)
- Method
- GET
- Endpoint
/jobs/{id}- Scope
jobs:read- Description
- Inspection with assets, signed URLs and latest findings
- Method
- GET
- Endpoint
/jobs/{id}/findings- Scope
jobs:read- Description
- Findings for one round with filters
- Method
- POST
- Endpoint
/jobs/{id}/fix- Scope
jobs:write- Description
- Apply auto-fixes and re-inspect
- Method
- POST
- Endpoint
/jobs/{id}/reinspect- Scope
jobs:write- Description
- Run a new round without changes
- Method
- GET
- Endpoint
/jobs/{id}/report- Scope
jobs:read- Description
- Full report as JSON
- Method
- GET
- Endpoint
/jobs/{id}/outputs- Scope
jobs:read- Description
- Final assets, or a ZIP with ?format=zip
- Method
- GET
- Endpoint
/openapi.json- Scope
—- Description
- OpenAPI 3.1 document (public)
| Method | Endpoint | Scope | Description |
|---|---|---|---|
| GET | /rules | rules:read | Supported markets, or the rule set for a country + platform |
| GET | /usage | jobs:read | Monthly quota and units used |
| GET | /jobs | jobs:read | List inspections (cursor pagination) |
| POST | /jobs | jobs:write | Create an inspection from images + text (multipart) |
| GET | /jobs/{id} | jobs:read | Inspection with assets, signed URLs and latest findings |
| GET | /jobs/{id}/findings | jobs:read | Findings for one round with filters |
| POST | /jobs/{id}/fix | jobs:write | Apply auto-fixes and re-inspect |
| POST | /jobs/{id}/reinspect | jobs:write | Run a new round without changes |
| GET | /jobs/{id}/report | jobs:read | Full report as JSON |
| GET | /jobs/{id}/outputs | jobs:read | Final assets, or a ZIP with ?format=zip |
| GET | /openapi.json | — | OpenAPI 3.1 document (public) |
Requests and responses use UTF-8 JSON, except POST /jobs which accepts multipart/form-data. Timestamps are ISO 8601 in UTC. Ids are UUIDs. Signed file URLs expire after one hour; request the resource again to get fresh links.
Authentication
Requests are authenticated with an organization API key sent as a Bearer token. Keys never expire but can be revoked at any time.
- 1Open Settings → API keys in the app and create a key. The plaintext key is shown once — store it in your secret manager.
- 2Send it on every request in the Authorization header. The x-api-key header is accepted as an alternative.
- 3Keys carry scopes. The default scopes are jobs:read and jobs:write; rules:read is enough for reading rule sets.
curl "https://dodam.modawn.ai/api/v1/usage" \
-H "Authorization: Bearer dk_live_XXXXXXXXXXXXXXXXXXXXXXXX"- Scope
jobs:read- Description
- Read inspections, findings, reports, outputs, usage and rule sets
- Scope
jobs:write- Description
- Create inspections, apply fixes, request re-inspections
- Scope
rules:read- Description
- Read markets and rule sets only
- Scope
*- Description
- All scopes
| Scope | Description |
|---|---|
jobs:read | Read inspections, findings, reports, outputs, usage and rule sets |
jobs:write | Create inspections, apply fixes, request re-inspections |
rules:read | Read markets and rule sets only |
* | All scopes |
A missing, malformed or revoked key returns 401 unauthorized; a valid key without the needed scope returns 403 forbidden. Keys are bound to one organization, so every job you create or read belongs to that organization.
{
"error": {
"code": "unauthorized",
"message": "Missing or invalid API key. Send `Authorization: Bearer dk_live_...`."
}
}Note
Keep keys server-side. Never embed dk_live_… keys in mobile apps or browser code — revoke and rotate a key immediately if it leaks.
Quotas & usage
Each organization has a monthly quota of inspection units. Reads are free; inspections and re-inspections consume units.
- Action
- Create an inspection
- Units
- 1 unit
- Action
- Re-inspection (also triggered by applying fixes)
- Units
- 1 unit
- Action
- All GET requests and downloads
- Units
- Free
| Action | Units |
|---|---|
| Create an inspection | 1 unit |
| Re-inspection (also triggered by applying fixes) | 1 unit |
| All GET requests and downloads | Free |
Units are counted per organization per calendar month (UTC) across the web app and every API key. When the quota is exhausted, POST /jobs and POST /jobs/{id}/fix respond with 429 quota_exhausted. Admins can see usage by key and by member in Settings → Usage.
/usagejobs:readcurl "https://dodam.modawn.ai/api/v1/usage" \
-H "Authorization: Bearer dk_live_XXXXXXXXXXXXXXXXXXXXXXXX"{
"plan": "starter",
"quota": 500,
"used": 37,
"remaining": 463,
"period": { "start": "2026-09-01T00:00:00.000Z", "end": "2026-10-01T00:00:00.000Z" },
"byKind": { "inspection": 29, "reinspection": 8 },
"thisKey": { "id": "3b8f…", "name": "Listing tool (prod)", "used": 12 }
}HTTP/1.1 429 Too Many Requests
{ "error": { "code": "quota_exhausted", "message": "Monthly inspection quota exhausted" } }Markets & rules
Rule sets are composed per country and platform: image spec, title rule, prohibited or risky expressions, IP references and required information.
/rulesrules:read | jobs:readCall it without parameters to list every supported country, platform and product category. Add country and platform to get the exact rule set the engine applies. Regular-expression internals are not exposed; each rule carries its stable code, category, severity, title, description, suggestion and whether it is auto-fixable.
curl "https://dodam.modawn.ai/api/v1/rules" \
-H "Authorization: Bearer dk_live_XXXXXXXXXXXXXXXXXXXXXXXX"curl "https://dodam.modawn.ai/api/v1/rules?country=US&platform=amazon" \
-H "Authorization: Bearer dk_live_XXXXXXXXXXXXXXXXXXXXXXXX"{
"rules": {
"country": "US", "countryName": "United States",
"platform": "amazon", "platformName": "Amazon",
"image": {
"minEdge": 500, "recommendedEdge": 1600, "maxEdge": 10000, "maxBytes": 10485760,
"formats": ["jpeg", "png", "gif"], "aspect": null,
"mainWhiteBackground": "required", "mainMinFill": 0.85, "noTextOnMain": true
},
"title": { "maxLength": 200, "minLength": 15, "recommendedMax": 80, "noAllCaps": true, "noPromoWords": true, "noSpecialChars": true },
"notes": ["Main image: pure white background (RGB 255,255,255), product fills 85%+ of frame", "…"],
"textRules": [
{
"code": "EXP_MEDICAL_CLAIM", "category": "expression", "severity": "critical",
"title": "Medical or disease claim",
"description": "Claims to cure, treat or prevent a disease make the product a drug…",
"suggestion": "Rephrase as an appearance or comfort benefit…",
"autoFixable": false, "fields": ["title", "bullets", "description"], "productCategories": null
}
],
"requiredInfo": [
{ "code": "REQ_ORIGIN", "category": "required_info", "severity": "warning", "title": "Country of origin missing", "autoFixable": true, "productCategories": null }
]
}
}17 countries · 13 platforms
United States US
English
Amazon · TikTok Shop · eBay · Walmart Marketplace · Temu · Shopify (own store)
United Kingdom GB
English
Amazon · TikTok Shop · eBay · Temu · Shopify (own store)
Germany DE
German
Amazon · eBay · Temu · Shopify (own store)
France FR
French
Amazon · Temu · Shopify (own store)
Japan JP
Japanese
Amazon · Rakuten · Qoo10 · Temu · Shopify (own store)
China CN
Chinese (Simplified)
Tmall Global · JD Worldwide · Shopify (own store)
Taiwan TW
Chinese (Traditional)
Shopee · Shopify (own store)
Hong Kong HK
Chinese (Traditional) / English
Shopify (own store)
Singapore SG
English
Amazon · Shopee · Lazada · TikTok Shop · Qoo10 · Shopify (own store)
Malaysia MY
Malay / English
Shopee · Lazada · TikTok Shop · Shopify (own store)
Thailand TH
Thai
Shopee · Lazada · TikTok Shop · Shopify (own store)
Vietnam VN
Vietnamese
Shopee · Lazada · TikTok Shop · Shopify (own store)
Indonesia ID
Indonesian
Shopee · Lazada · TikTok Shop · Shopify (own store)
Philippines PH
English / Filipino
Shopee · Lazada · TikTok Shop · Shopify (own store)
Australia AU
English
Amazon · eBay · Temu · Shopify (own store)
United Arab Emirates AE
Arabic / English
Amazon · noon · Shopify (own store)
Saudi Arabia SA
Arabic
Amazon · noon · Shopify (own store)
- Platform
- Amazon
- Code
amazon- Countries
- US, GB, DE, FR, JP, SG, AE, SA, AU
- Platform
- Shopee
- Code
shopee- Countries
- SG, MY, TH, VN, ID, PH, TW
- Platform
- Lazada
- Code
lazada- Countries
- SG, MY, TH, VN, ID, PH
- Platform
- TikTok Shop
- Code
tiktok_shop- Countries
- US, GB, SG, MY, TH, VN, ID, PH
- Platform
- Rakuten
- Code
rakuten- Countries
- JP
- Platform
- Qoo10
- Code
qoo10- Countries
- JP, SG
- Platform
- Tmall Global
- Code
tmall_global- Countries
- CN
- Platform
- JD Worldwide
- Code
jd_worldwide- Countries
- CN
- Platform
- noon
- Code
noon- Countries
- AE, SA
- Platform
- eBay
- Code
ebay- Countries
- US, GB, DE, AU
- Platform
- Walmart Marketplace
- Code
walmart- Countries
- US
- Platform
- Temu
- Code
temu- Countries
- US, GB, DE, FR, JP, AU
- Platform
- Shopify (own store)
- Code
shopify- Countries
- All
| Platform | Code | Countries |
|---|---|---|
| Amazon | amazon | US, GB, DE, FR, JP, SG, AE, SA, AU |
| Shopee | shopee | SG, MY, TH, VN, ID, PH, TW |
| Lazada | lazada | SG, MY, TH, VN, ID, PH |
| TikTok Shop | tiktok_shop | US, GB, SG, MY, TH, VN, ID, PH |
| Rakuten | rakuten | JP |
| Qoo10 | qoo10 | JP, SG |
| Tmall Global | tmall_global | CN |
| JD Worldwide | jd_worldwide | CN |
| noon | noon | AE, SA |
| eBay | ebay | US, GB, DE, AU |
| Walmart Marketplace | walmart | US |
| Temu | temu | US, GB, DE, FR, JP, AU |
| Shopify (own store) | shopify | All |
Product categories
beautysupplementfoodfashionelectronicshomebabytoyspetotherPassing a product category enables category-specific rules — supplement disclaimers, allergen labels, toy age grading and so on.
Create an inspection
Upload the detail-page images and listing text in one multipart request. The engine runs synchronously and the response already contains the findings.
/jobsjobs:write- Field
images- Type
file[]- Required
- Required
- Description
- 1–20 images (JPEG, PNG, WEBP, GIF), 25 MB each. Repeat the part for each file.
- Field
country- Type
string- Required
- Required
- Description
- ISO 3166-1 alpha-2, e.g. US. See GET /rules.
- Field
platform- Type
string- Required
- Required
- Description
- Platform code, e.g. amazon. Must be available in that country.
- Field
name- Type
string- Required
- Optional
- Description
- Inspection name shown in the app. Defaults to the product title.
- Field
product_category- Type
string- Required
- Optional
- Description
- One of beauty, supplement, food, fashion, electronics, home, baby, toys, pet, other.
- Field
title- Type
string- Required
- Optional
- Description
- Product title (≤ 500 characters).
- Field
bullets- Type
string- Required
- Optional
- Description
- Key features as a JSON array of strings, or newline-separated text.
- Field
description- Type
string- Required
- Optional
- Description
- Product description (≤ 20,000 characters).
- Field
main_index- Type
integer- Required
- Optional
- Description
- Index of the main image inside images. Default 0.
- Field
locale- Type
string- Required
- Optional
- Description
- en or ko — language for suggestions. Default en.
| Field | Type | Required | Description |
|---|---|---|---|
images | file[] | Required | 1–20 images (JPEG, PNG, WEBP, GIF), 25 MB each. Repeat the part for each file. |
country | string | Required | ISO 3166-1 alpha-2, e.g. US. See GET /rules. |
platform | string | Required | Platform code, e.g. amazon. Must be available in that country. |
name | string | Optional | Inspection name shown in the app. Defaults to the product title. |
product_category | string | Optional | One of beauty, supplement, food, fashion, electronics, home, baby, toys, pet, other. |
title | string | Optional | Product title (≤ 500 characters). |
bullets | string | Optional | Key features as a JSON array of strings, or newline-separated text. |
description | string | Optional | Product description (≤ 20,000 characters). |
main_index | integer | Optional | Index of the main image inside images. Default 0. |
locale | string | Optional | en or ko — language for suggestions. Default en. |
curl -X POST "https://dodam.modawn.ai/api/v1/jobs" \
-H "Authorization: Bearer dk_live_XXXXXXXXXXXXXXXXXXXXXXXX" \
-F "name=Vitamin C serum — Amazon US" \
-F "country=US" \
-F "platform=amazon" \
-F "product_category=beauty" \
-F "title=Glow Vitamin C Serum 30ml" \
-F 'bullets=["20% pure vitamin C", "Cures acne in 3 days"]' \
-F "description=Brightening serum for all skin types." \
-F "main_index=0" \
-F "images=@main.jpg" \
-F "images=@detail-1.jpg" \
-F "images=@detail-2.jpg"import { openAsBlob } from "node:fs";
const form = new FormData();
form.append("name", "Vitamin C serum — Amazon US");
form.append("country", "US");
form.append("platform", "amazon");
form.append("title", "Glow Vitamin C Serum 30ml");
form.append("bullets", JSON.stringify(["20% pure vitamin C", "Cures acne in 3 days"]));
form.append("images", await openAsBlob("main.jpg"), "main.jpg");
form.append("images", await openAsBlob("detail-1.jpg"), "detail-1.jpg");
const res = await fetch("https://dodam.modawn.ai/api/v1/jobs", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.DODAM_API_KEY}` },
body: form,
});
const { job, findings } = await res.json();
console.log(job.score, job.verdict, findings.length);The request blocks while the engine runs, typically 1–5 seconds for a handful of images. The response has the same shape as GET /jobs/{id}: the job with score and verdict, the assets with signed URLs and the findings of round 1.
HTTP/1.1 201 Created
Location: /api/v1/jobs/6f1c2a4e-8d3b-4f0a-9c1e-2b7d5e9a1f33
{
"job": {
"id": "6f1c2a4e-8d3b-4f0a-9c1e-2b7d5e9a1f33",
"name": "Vitamin C serum — Amazon US",
"status": "review",
"round": 1,
"score": 74,
"verdict": "needs_fix",
"market": { "country": "US", "countryName": "United States", "platform": "amazon", "platformName": "Amazon", "productCategory": "beauty" },
"text": { "title": "Glow Vitamin C Serum 30ml", "bullets": ["20% pure vitamin C", "Cures acne in 3 days"], "description": "Brightening serum for all skin types." },
"summary": { "critical": 1, "warning": 2, "info": 1, "byCategory": { "spec": 1, "expression": 1, "required_info": 2 }, "assets": 3, "engine": "rules", "durationMs": 842 },
"aiEnriched": false,
"source": "api",
"createdAt": "2026-09-02T09:14:03.120Z",
"completedAt": "2026-09-02T09:14:04.011Z"
},
"assets": [
{ "id": "a7d0…", "filename": "main.jpg", "role": "main", "mime": "image/jpeg", "width": 1200, "height": 1200, "sizeBytes": 412088,
"currentVersion": 1, "originalUrl": "https://…/v1.jpg?token=…", "currentUrl": "https://…/v1.jpg?token=…", "versions": [] }
],
"findings": [
{
"id": "f1e2…", "assetId": "a7d0…", "round": 1,
"category": "spec", "severity": "critical", "priority": 1,
"code": "IMG_BG_NOT_WHITE",
"title": "Main image background is not pure white",
"evidence": { "location": "image", "measured": "91% white", "expected": "≥ 98% white", "source": "rules" },
"suggestion": "Whiten the background to RGB 255,255,255.",
"fix": { "type": "whiten_background", "threshold": 235 },
"autoFixable": true, "status": "open"
},
{
"id": "f2c9…", "assetId": null, "round": 1,
"category": "expression", "severity": "critical", "priority": 1,
"code": "EXP_MEDICAL_CLAIM",
"title": "Medical or disease claim",
"evidence": { "location": "bullet:2", "matched": "Cures acne", "source": "rules" },
"suggestion": "Rephrase as an appearance or comfort benefit, e.g. “helps reduce the look of blemishes”, or remove the claim.",
"fix": null, "autoFixable": false, "status": "open"
},
{
"id": "f3a1…", "assetId": null, "round": 1,
"category": "required_info", "severity": "warning", "priority": 2,
"code": "REQ_ORIGIN",
"title": "Country of origin missing",
"suggestion": "Add “Country of origin: Republic of Korea” to the description.",
"fix": { "type": "append_text", "field": "description", "text": "Country of origin: Republic of Korea" },
"autoFixable": true, "status": "open"
}
],
"rounds": [1]
}Tip
Sending bullets as a JSON array preserves each feature exactly. Set main_index when the first image is not the hero image — main-image rules (white background, fill ratio, no text) only apply to that asset.
Get results
List inspections with cursor pagination, fetch a single inspection with signed image URLs, or page through findings per round.
/jobsjobs:readReturns the newest inspections first. limit is 1–100 (default 20). Filter with status, country or platform. When nextCursor is not null, pass it as cursor to fetch the next page.
curl "https://dodam.modawn.ai/api/v1/jobs?limit=20&status=review" \
-H "Authorization: Bearer dk_live_XXXXXXXXXXXXXXXXXXXXXXXX"
# next page
curl "https://dodam.modawn.ai/api/v1/jobs?limit=20&cursor=2026-09-02T09:14:03.120Z" \
-H "Authorization: Bearer dk_live_XXXXXXXXXXXXXXXXXXXXXXXX"{
"jobs": [ { "id": "6f1c2a4e-8d3b-4f0a-9c1e-2b7d5e9a1f33", "name": "Vitamin C serum — Amazon US", "status": "review", "round": 1, "score": 74, "verdict": "needs_fix", "…": "…" } ],
"nextCursor": "2026-09-02T09:14:03.120Z",
"limit": 20
}/jobs/{id}jobs:readEverything about one inspection: the job, every image asset with originalUrl, currentUrl and its fix versions, plus the findings of the latest round. Signed URLs are valid for one hour.
curl "https://dodam.modawn.ai/api/v1/jobs/6f1c2a4e-8d3b-4f0a-9c1e-2b7d5e9a1f33" \
-H "Authorization: Bearer dk_live_XXXXXXXXXXXXXXXXXXXXXXXX"/jobs/{id}/findingsjobs:readFindings for a given round (default: latest), optionally filtered by category, severity and status. Previous rounds keep their findings, so you can show how a listing improved after fixes.
curl "https://dodam.modawn.ai/api/v1/jobs/6f1c2a4e-8d3b-4f0a-9c1e-2b7d5e9a1f33/findings?round=1&severity=critical" \
-H "Authorization: Bearer dk_live_XXXXXXXXXXXXXXXXXXXXXXXX"{
"jobId": "6f1c2a4e-8d3b-4f0a-9c1e-2b7d5e9a1f33",
"round": 1,
"latestRound": 2,
"rounds": [1, 2],
"score": null,
"verdict": null,
"findings": [ { "id": "f1e2…", "code": "IMG_BG_NOT_WHITE", "severity": "critical", "status": "fixed", "…": "…" } ]
}Note
A job is completed when the latest round passes, and review while findings remain. Amazon-style markets (US, GB, DE, FR, JP, SG, AE, SA, AU) enforce the strictest main-image spec — check assets[].role to find the main image.
Findings model
Every issue is a finding with a category, a severity, a stable rule code, evidence, a suggestion and, when possible, an executable fix action.
Categories
- Code
- spec
- Meaning
- Platform spec violation: image size, ratio, format, file size, background, title length and style
- Code
- expression
- Meaning
- Prohibited or risky expression: medical and absolute claims, superlatives, promo words, external contact details
- Code
- rights
- Meaning
- IP and rights risk: third-party brands, characters, celebrities, regulator endorsements
- Code
- required_info
- Meaning
- Missing required information: origin, responsible person, disclaimers, local-language content, certifications
- Code
- quality
- Meaning
- Image quality risk: blur, low brightness or contrast, blank frames, unreadable files
| Code | Meaning |
|---|---|
| spec | Platform spec violation: image size, ratio, format, file size, background, title length and style |
| expression | Prohibited or risky expression: medical and absolute claims, superlatives, promo words, external contact details |
| rights | IP and rights risk: third-party brands, characters, celebrities, regulator endorsements |
| required_info | Missing required information: origin, responsible person, disclaimers, local-language content, certifications |
| quality | Image quality risk: blur, low brightness or contrast, blank frames, unreadable files |
Severities
- Code
- critical
- Weight
- −15
- Priority
1
- Code
- warning
- Weight
- −5
- Priority
2
- Code
- info
- Weight
- −1
- Priority
3
| Code | Weight | Priority |
|---|---|---|
| critical | −15 | 1 |
| warning | −5 | 2 |
| info | −1 | 3 |
Score and verdict
The score starts at 100 and subtracts 15 per critical, 5 per warning and 1 per info finding (floored at 0).
score = max(0, 100 − (15 × critical + 5 × warning + 1 × info))
pass— score ≥ 85 and no critical findingneeds_fix— score 60–84, or any critical findingfail— score < 60
Finding statuses
- Status
open- Meaning
- Detected in the latest round and not yet decided
- Status
accepted- Meaning
- Reviewer agreed with the finding (still eligible for auto-fix)
- Status
dismissed- Meaning
- Reviewer marked it as not applicable
- Status
disputed- Meaning
- Reviewer disagrees; kept for the record
- Status
fixed- Meaning
- Applied through POST /jobs/{id}/fix — set automatically
| Status | Meaning |
|---|---|
open | Detected in the latest round and not yet decided |
accepted | Reviewer agreed with the finding (still eligible for auto-fix) |
dismissed | Reviewer marked it as not applicable |
disputed | Reviewer disagrees; kept for the record |
fixed | Applied through POST /jobs/{id}/fix — set automatically |
Fix actions
When autoFixable is true, fix describes the exact action Dodam will run. Image actions create a new asset version; text actions rewrite the job's title, bullets or description.
- Type
resize- Description
- Resize (and optionally pad to square) to the platform's min / max edge
- Type
convert- Description
- Re-encode as jpeg, png or webp
- Type
compress- Description
- Reduce file size below maxBytes
- Type
whiten_background- Description
- Push near-white background pixels to pure white
- Type
crop_to_content- Description
- Crop margins so the product fills the frame
- Type
strip_metadata- Description
- Remove EXIF / ICC metadata
- Type
replace_text- Description
- Replace `from` with `to` in the given text field
- Type
append_text- Description
- Append a required line to the given text field
| Type | Description |
|---|---|
resize | Resize (and optionally pad to square) to the platform's min / max edge |
convert | Re-encode as jpeg, png or webp |
compress | Reduce file size below maxBytes |
whiten_background | Push near-white background pixels to pure white |
crop_to_content | Crop margins so the product fills the frame |
strip_metadata | Remove EXIF / ICC metadata |
replace_text | Replace `from` with `to` in the given text field |
append_text | Append a required line to the given text field |
Job statuses
- Status
processing- Meaning
- Engine is running (only visible on very large uploads)
- Status
review- Meaning
- Latest round has findings to review
- Status
fixing- Meaning
- Fixes are being applied
- Status
completed- Meaning
- Latest round passed
- Status
failed- Meaning
- Engine error — retry with POST /jobs/{id}/reinspect
| Status | Meaning |
|---|---|
processing | Engine is running (only visible on very large uploads) |
review | Latest round has findings to review |
fixing | Fixes are being applied |
completed | Latest round passed |
failed | Engine error — retry with POST /jobs/{id}/reinspect |
Rule codes (25 text rules · 52 required-info rules · 20 image rules)ShowHide
Image (IMG_*) and title (TITLE_*)
IMG_FORMATIMG_TOO_SMALLIMG_BELOW_RECOMMENDEDIMG_TOO_LARGEIMG_FILE_TOO_BIGIMG_ASPECTIMG_BG_NOT_WHITEIMG_BG_RECOMMEND_WHITEIMG_TRANSPARENTIMG_FILL_LOWIMG_BLURRYIMG_SOFTIMG_DARKIMG_BLANKIMG_LOW_CONTRASTIMG_METADATAIMG_UNREADABLETITLE_TOO_LONGTITLE_LONG_MOBILETITLE_TOO_SHORTTITLE_ALL_CAPSTITLE_MISSINGExpressions and rights (EXP_*)
EXP_MEDICAL_CLAIMEXP_ANTI_MEDICALEXP_REGULATOR_APPROVALEXP_WEIGHT_LOSSEXP_SKIN_WHITENINGEXP_WHITENINGEXP_CLINICALEXP_ABSOLUTE_NATURALEXP_ABSOLUTE_SAFEEXP_SUPERLATIVE_BESTEXP_SUPERLATIVE_NO1EXP_CN_ABSOLUTEEXP_INSTANTEXP_INSTANT_TIMEEXP_MIRACLEEXP_COMPARATIVEEXP_EXTERNAL_CONTACTEXP_PROMO_TITLEEXP_EMOJI_TITLEEXP_PUNCTUATIONRGT_BRAND_REFERENCERGT_REPLICARGT_CELEBRITYRGT_PATENTRGT_OFFICIALRequired information (REQ_*)
REQ_ORIGINREQ_INGREDIENTSREQ_NET_CONTENTREQ_SHELF_LIFEREQ_ALLERGENREQ_AGE_GRADEREQ_FIBER_CONTENTREQ_CAREREQ_BATTERYREQ_US_FDA_DISCLAIMERREQ_US_SUPPLEMENT_FACTSREQ_US_NUTRITIONREQ_US_FCCREQ_US_CPSIAREQ_GB_RPREQ_GB_UKCAREQ_GB_ALLERGEN_ENREQ_EU_RPREQ_EU_CEREQ_DE_LANGREQ_EU_WEEEREQ_FR_LANGREQ_FR_TRIMANREQ_JP_LANGREQ_JP_SELLERREQ_JP_COSMETIC_CLASSREQ_JP_PSEREQ_JP_STREQ_CN_LANGREQ_CN_CROSS_BORDERREQ_CN_CCCREQ_TW_LANGREQ_HK_LANGREQ_TH_LANGREQ_TH_FDAREQ_VN_LANGREQ_ID_LANGREQ_ID_BPOMREQ_ID_HALALREQ_MY_NPRAREQ_MY_HALALREQ_PH_FDAREQ_SG_HSAREQ_AU_RCMREQ_AU_AICISREQ_AE_ARABICREQ_AE_ESMAREQ_AE_HALALREQ_SA_ARABICREQ_SA_SFDAREQ_SA_SABERREQ_SA_HALALApply fixes & re-inspect
Send the ids of auto-fixable findings to apply them. Dodam creates a new version of each touched image, updates the text and runs a new round.
/jobs/{id}/fixjobs:writePass the ids of findings from the current round that are autoFixable and still open or accepted. Text fixes are applied to the listing text; image fixes produce version n + 1 of each touched asset. The job is then re-inspected and the response contains the new round (1 unit).
curl -X POST "https://dodam.modawn.ai/api/v1/jobs/6f1c2a4e-8d3b-4f0a-9c1e-2b7d5e9a1f33/fix" \
-H "Authorization: Bearer dk_live_XXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{ "findingIds": ["f1e2…", "f3a1…"] }'{
"applied": 2,
"round": 2,
"score": 85,
"verdict": "needs_fix",
"job": { "id": "6f1c2a4e-8d3b-4f0a-9c1e-2b7d5e9a1f33", "status": "review", "round": 2, "score": 85, "verdict": "needs_fix", "…": "…" },
"assets": [
{ "id": "a7d0…", "filename": "main.jpg", "role": "main", "currentVersion": 2, "currentUrl": "https://…/v2.jpg?token=…",
"versions": [ { "version": 2, "url": "https://…/v2.jpg?token=…", "appliedFindingIds": ["f1e2…"], "appliedFixes": [ { "type": "whiten_background", "threshold": 235 } ] } ] }
],
"findings": [ { "id": "f4b7…", "round": 2, "code": "EXP_MEDICAL_CLAIM", "severity": "critical", "status": "open", "…": "…" } ],
"rounds": [1, 2]
}Note
Findings that cannot be fixed automatically — for example a medical claim that needs rewriting — keep fix: null. Update your listing text, then call POST /jobs/{id}/reinspect or create a new inspection with the corrected content.
/jobs/{id}/reinspectjobs:writeRuns a fresh round on the current assets and text without changing anything, which is useful after a manual review or when rules are updated. The optional note is stored in the job timeline. Costs 1 unit.
curl -X POST "https://dodam.modawn.ai/api/v1/jobs/6f1c2a4e-8d3b-4f0a-9c1e-2b7d5e9a1f33/reinspect" \
-H "Authorization: Bearer dk_live_XXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{ "note": "Text updated in our PIM" }'Outputs & downloads
Retrieve the final version of every image, the report and a ZIP bundle. Downloads are logged in the inspection's download history.
/jobs/{id}/outputsjobs:readOne entry per image with the signed URL of its latest version, the current listing text, and links to the report and ZIP. URLs expire after urlExpiresInSeconds; call the endpoint again for fresh ones.
curl "https://dodam.modawn.ai/api/v1/jobs/6f1c2a4e-8d3b-4f0a-9c1e-2b7d5e9a1f33/outputs" \
-H "Authorization: Bearer dk_live_XXXXXXXXXXXXXXXXXXXXXXXX"{
"jobId": "6f1c2a4e-8d3b-4f0a-9c1e-2b7d5e9a1f33",
"round": 2,
"score": 85,
"verdict": "needs_fix",
"assets": [
{ "id": "a7d0…", "filename": "main.jpg", "role": "main", "currentVersion": 2, "url": "https://…/v2.jpg?token=…", "mime": "image/jpeg", "width": 1600, "height": 1600, "sizeBytes": 388120 }
],
"text": { "title": "Glow Vitamin C Serum 30ml", "bullets": ["20% pure vitamin C", "Cures acne in 3 days"], "description": "Brightening serum for all skin types.\nCountry of origin: Republic of Korea" },
"reportUrl": "https://dodam.modawn.ai/api/v1/jobs/6f1c2a4e-8d3b-4f0a-9c1e-2b7d5e9a1f33/report",
"zipUrl": "https://dodam.modawn.ai/api/v1/jobs/6f1c2a4e-8d3b-4f0a-9c1e-2b7d5e9a1f33/outputs?format=zip",
"urlExpiresInSeconds": 3600
}/jobs/{id}/outputs?format=zipjobs:readStreams application/zip containing final/ (every image at its latest version, named by order, role and version), report.json and listing-text.txt. Each download is written to the inspection's download log.
curl -L "https://dodam.modawn.ai/api/v1/jobs/6f1c2a4e-8d3b-4f0a-9c1e-2b7d5e9a1f33/outputs?format=zip" \
-H "Authorization: Bearer dk_live_XXXXXXXXXXXXXXXXXXXXXXXX" \
-o final-assets.zip/jobs/{id}/reportjobs:readThe full report: inspection metadata, market, text, summary, findings of the latest round, history per round, assets with every version, the applied rule highlights and the event timeline. The same document is embedded in the ZIP.
curl "https://dodam.modawn.ai/api/v1/jobs/6f1c2a4e-8d3b-4f0a-9c1e-2b7d5e9a1f33/report" \
-H "Authorization: Bearer dk_live_XXXXXXXXXXXXXXXXXXXXXXXX" | jq .report.summaryErrors
Errors use conventional HTTP status codes and a JSON body with a stable machine-readable code.
HTTP/1.1 400 Bad Request
{
"error": {
"code": "validation_error",
"message": "Invalid request: country must be a 2-letter ISO code",
"details": [ { "field": "country", "message": "country must be a 2-letter ISO code" } ]
}
}- HTTP
400- Code
validation_error- Meaning
- A parameter or field is missing or invalid — details lists the fields
- HTTP
401- Code
unauthorized- Meaning
- No key, malformed key, unknown or revoked key
- HTTP
403- Code
forbidden- Meaning
- Key lacks the scope, or the job belongs to another organization
- HTTP
404- Code
not_found- Meaning
- Unknown job id
- HTTP
415- Code
unsupported_media_type- Meaning
- POST /jobs body is not multipart/form-data
- HTTP
429- Code
quota_exhausted- Meaning
- The organization's monthly quota is used up
- HTTP
500- Code
internal_error- Meaning
- Unexpected failure — safe to retry
| HTTP | Code | Meaning |
|---|---|---|
400 | validation_error | A parameter or field is missing or invalid — details lists the fields |
401 | unauthorized | No key, malformed key, unknown or revoked key |
403 | forbidden | Key lacks the scope, or the job belongs to another organization |
404 | not_found | Unknown job id |
415 | unsupported_media_type | POST /jobs body is not multipart/form-data |
429 | quota_exhausted | The organization's monthly quota is used up |
500 | internal_error | Unexpected failure — safe to retry |
Tip
Branch on error.code, not on the message — messages may be reworded, codes are stable. Retry 500 with exponential back-off; never retry 4xx without changing the request.
OpenAPI
The whole API is described by an OpenAPI 3.1 document that you can import into Postman, Insomnia or an SDK generator.
https://dodam.modawn.ai/api/v1/openapi.jsoncurl "https://dodam.modawn.ai/api/v1/openapi.json" -o dodam-openapi.json
# e.g. generate a TypeScript client
npx openapi-typescript dodam-openapi.json -o dodam-api.d.tsThe document's servers entry always points at the deployment you fetched it from, so a generated client targets the right environment without extra configuration.
Questions about the API? Contact your Dodam AI account manager.