Virtual Try-On API
একজন ব্যক্তির ছবি এবং একটি পোশাকের ছবি পাঠান — সেই ব্যক্তি সেই পোশাক পরে আছেন এমন একটি ফটোরিয়েলিস্টিক ছবি ফেরত পান। একটি জব পাঠান, তারপর ফলাফলের জন্য পোল করুন অথবা আমাদের কলব্যাক নিন।
গুরুত্বপূর্ণ পরিবর্তন
এই API আগে পুরোপুরি সিঙ্ক্রোনাস ছিল — একটি রিকোয়েস্ট, একটি ব্লকিং রেসপন্স, যার সাথেই তৈরি হওয়া ছবি আসত। এখন এটি অ্যাসিনক্রোনাস।POST /v1/tryon (এবং /upload) সাথে সাথেই 202 সহ একটি জব আইডি ফেরত দেয়; ফলাফল পেতে হয় GET /v1/tryon/jobs/{id} পোল করে, নয়তো একটি callback_url দিয়ে। আপনি যদি এই ডকুমেন্টেশনের পুরোনো সংস্করণ ধরে ইন্টিগ্রেট করে থাকেন, সেটি হালনাগাদ করুন — আগের এক-কলেই-সব পদ্ধতি আর কাজ করে না।AI কোডিং এজেন্ট ব্যবহার করছেন?
প্রতিটি এন্ডপয়েন্ট, ফিল্ড, জব স্ট্যাটাস ও এরর কোডসহ সংক্ষিপ্ত markdown স্পেক ডাউনলোড করুন — অথবা সরাসরি চ্যাটে কপি করে নিন। ফাইলটি শুধু ইংরেজিতে।
ড্যাশবোর্ড থেকে API Key তৈরি করুন
আপনার BenitoAI ড্যাশবোর্ডের API keys ট্যাব খুলে কয়েক ক্লিকেই একটি কী তৈরি করে নিন। কী শুধু একবারই দেখানো হয়, তৈরির সময় — সেটি সরাসরি আপনার সার্ভারের সিক্রেট স্টোরে কপি করে রাখুন। চাইলে সেখান থেকেই আলাদা কোনো কী-এর জন্য নিজস্ব ক্রেডিট লিমিটও বেঁধে দিতে পারেন।
মূল ধারণা
প্রথমে এগুলো পড়ুন — এগুলো আপনার ইন্টিগ্রেশনের ধরন নির্ধারণ করে।
- অ্যাসিনক্রোনাস জব মডেল। রিকোয়েস্ট পাঠালে সাথে সাথেই একটি জব আইডি ফেরত আসে — জেনারেশন শেষ হওয়ার জন্য এটি অপেক্ষা করে না। এরপর আপনি হয়
GET /v1/tryon/jobs/{id}পোল করবেন যতক্ষণ নাstatuscompleted(বাfailed) হয়, নয়তো একটিcallback_urlদেবেন এবং কাজ শেষ হলে আমরা সেখানে জবটিPOSTকরব। দুটি ব্যবস্থাই সবসময় খোলা থাকে —callback_urlদিয়েছেন বলে পোলিং বন্ধ হয়ে যায় না। - জেনারেশনে প্রায় ১০–৬০ সেকেন্ড লাগে জব প্রসেস হওয়া শুরু করার পর, সাথে কিউতে অপেক্ষার সময় যোগ হতে পারে। তাই একটি দীর্ঘ সংযোগ ধরে রাখার বদলে পরে ফিরে এসে খোঁজ নেওয়ার কথা মাথায় রেখে ইন্টিগ্রেশন সাজান (১–৩ সেকেন্ড পর পর পোল করা যুক্তিসঙ্গত)।
- ছবি দেওয়ার দুটি উপায়।
POST /v1/tryonJSON নেয়, যেখানে ছবির URLhttp/https-এ সর্বজনীনভাবে অ্যাক্সেসযোগ্য হতে হয় — সার্ভার নিজেই সেগুলো ডাউনলোড করে।POST /v1/tryon/uploadনেয়multipart/form-data, যাতে আপনি সরাসরি ফাইলটাই আপলোড করতে পারেন — শুধু এই API যেন ছবিটি ডাউনলোড করতে পারে সেজন্য আগে কোথাও পাবলিকলি হোস্ট করার ঝামেলা বাঁচে। - আউটপুট একটি হোস্টেড PNG URL। API কখনো base64 ফেরত দেয় না — আপনি তৈরি হওয়া
.png-এর একটি URL পান।
অথেন্টিকেশন
প্রতিটি রিকোয়েস্টে Authorization হেডারে একটি Bearer API Key প্রয়োজন:
Authorization: Bearer bnto_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx- কী-এর শুরুতে থাকে
bnto_live_, তারপর একটি এলোমেলো স্ট্রিং। - কী শুধুমাত্র একবার, তৈরির সময় দেখানো হয় — আপনারটি নিরাপদে সংরক্ষণ করুন।
- অনুপস্থিত, ভুল ফরম্যাটের, বাতিল করা, বা অজানা কী
401ফেরত দেয়। - কী-কে একটি গোপনীয় তথ্য হিসেবে বিবেচনা করুন: এটি কখনো ক্লায়েন্ট-সাইড/ব্রাউজার কোডে এম্বেড করবেন না বা সোর্স কন্ট্রোলে কমিট করবেন না। আপনার ব্যাকএন্ড থেকে API কল করুন।
ক্রেডিট ও কোটা
গৃহীত প্রতিটি try-on-এর খরচ একটি ক্রেডিট, যা কাটা হয় সাবমিট করার সময় — জব শেষ হওয়ার সময় নয়। কোনো জব failed হলে সেটি স্বয়ংক্রিয়ভাবে ফেরত দেওয়া হয়, ফলে আপনি কেবল সত্যিই পাওয়া জেনারেশনের জন্যই টাকা দেন। এই খরচ মেটায় দুটি হিসাব, এই ক্রমে:
- প্ল্যান কোটা — আপনার মাসিক প্ল্যানে অন্তর্ভুক্ত try-on সংখ্যা। প্রতি বিলিং সাইকেলে রিসেট হয়; অব্যবহৃত কোটা পরের মাসে যায় না, এবং সাইকেল শেষ হওয়ামাত্র সেটি আর খরচ করা যায় না।
- কেনা ক্রেডিট — আলাদাভাবে কেনা টপ-আপ। এগুলোর মেয়াদ কখনো শেষ হয় না এবং সাবস্ক্রিপশন বন্ধ হয়ে গেলেও থেকে যায়। কোটা ফুরিয়ে গেলে অতিরিক্ত ব্যবহারের খরচ এগুলো থেকেই কাটে।
ক্রেডিট আপনার অ্যাকাউন্টের, কোনো নির্দিষ্ট কী-এর নয়। আপনার সব API Key একই পুল থেকে খরচ করে — তিনটি কী দিয়ে দুটি করে try-on চালালে মোট ছয়টি ক্রেডিট খরচ হয়। চাইলে আলাদা কোনো কী-এর জন্য নিজস্ব ক্রেডিট লিমিট বেঁধে দিতে পারেন, যা ঠিক করে দেয় সেই কী শেয়ার করা পুল থেকে সর্বোচ্চ কতটা খরচ করতে পারবে। এটি একটি সর্বোচ্চ সীমা, আলাদা বরাদ্দ নয় — এতে খরচের ক্ষমতা বাড়ে না।
কোনো হিসাবেই যদি কলটির খরচ না মেটে, আপনি 402 insufficient_credits পাবেন এবং কিছুই কিউতে যাবে না। অ্যাকাউন্টে ক্রেডিট থাকা সত্ত্বেও কী-টির নিজের লিমিট শেষ হয়ে গেলে বদলে পাবেন 402 key_credit_limit_reached — একই স্ট্যাটাস, কিন্তু সমাধান ভিন্ন, তাই code দেখে নিন।
জব পাঠানো
এন্ডপয়েন্টে একটি JSON বডি পাঠান। রেসপন্স সাথে সাথেই আসে এবং তাতে ছবি থাকে না।
বডি স্কিমা:
{
"model_name": "tryon-v1.6",
"inputs": {
"model_image": "https://example.com/person.jpg",
"garment_image": "https://example.com/garment.jpg"
},
"callback_url": "https://your-server.example/webhooks/tryon"
}| ফিল্ড | টাইপ | আবশ্যক | বিবরণ |
|---|---|---|---|
model_name | string | না | লজিক্যাল মডেল আইডেন্টিফায়ার। ডিফল্ট tryon-v1.6। রেসপন্সে ফেরত আসে। |
inputs.model_image | URL | হ্যাঁ | ব্যক্তি/মডেলের ছবির সর্বজনীন URL। এই ছবিই আউটপুটের পরিচয়, ভঙ্গি, ব্যাকগ্রাউন্ড ও aspect ratio ঠিক করে। |
inputs.garment_image | URL | শর্তসাপেক্ষ | garment_image / garment_id-এর ঠিক একটি দিতে হবে। পোশাকের ছবির সর্বজনীন URL। শুধু কাপড়, কাট ও রঙের রেফারেন্স হিসেবে ব্যবহৃত হয় — এর ব্যাকগ্রাউন্ড ধরা হয় না। |
inputs.garment_id | string | শর্তসাপেক্ষ | garment_image / garment_id-এর ঠিক একটি দিতে হবে। ড্যাশবোর্ড থেকে নিবন্ধন করা একটি গার্মেন্ট প্রিসেটের আইডি, যেমন grm_V1StGXR8Z5jdHi6BmyT। নিচের গার্মেন্ট প্রিসেট অংশ দেখুন। |
callback_url | URL | না | দিলে, জব শেষ বা ব্যর্থ হওয়ামাত্র আমরা সেটির এনভেলপ এখানে POST করি। কলব্যাক অংশ দেখুন। যেভাবেই হোক পোলিং খোলা থাকে। |
সফলভাবে পাঠাতে পারলে 202 সহ একটি জব আইডি ফেরত আসে — নিচের সাবমিট রেসপন্স দেখুন, তারপর ফলাফলের জন্য পোলিং।
model_image হলো ব্যক্তি; garment_image হলো পোশাক। ব্যক্তির মুখ, শরীর, ভঙ্গি ও ব্যাকগ্রাউন্ড অক্ষত থাকে; পোশাকটি তার গায়ে বসিয়ে দেওয়া হয়।গার্মেন্ট প্রিসেট
বেশিরভাগ ইন্টিগ্রেশনে একই পোশাকের ছবি বারবার পাঠানো হয়, শুধু ব্যক্তির ছবি প্রতিবার বদলায়। এমন ক্ষেত্রে প্রতিবার URL পাঠানোর বদলে প্রতিটি পোশাক ড্যাশবোর্ডে একবার নিবন্ধন করে নিন: আমরা আগেই ছবিটি পরিষ্কার করে রাখি — পোশাকটিকে সোজাসুজি করে একটি সাদামাটা ব্যাকগ্রাউন্ডে আলাদা করে নেওয়া হয় — সেটি সংরক্ষণ করি, এবং আপনাকে একটি স্থায়ী garment_id দিই।
- ফল ভালো হয় — মডেল তখন এলোমেলো ব্যাকগ্রাউন্ডে অন্য কারও পরনে থাকা ছবির বদলে একটি পরিষ্কার পোশাকের রেফারেন্স ধরে কাজ করে।
- শুরু হয় দ্রুত — প্রতিবার পোশাকের ছবি নামানো ও প্রস্তুত করার ধাপটি বাদ যায়, কারণ সেটি আগে থেকেই সংরক্ষিত ও তৈরি থাকে।
একই রিকোয়েস্ট, URL-এর বদলে প্রিসেট দিয়ে:
{
"model_name": "tryon-v1.6",
"inputs": {
"model_image": "https://example.com/person.jpg",
"garment_id": "grm_V1StGXR8Z5jdHi6BmyT"
}
}প্রিসেট এই API দিয়ে নয়, ড্যাশবোর্ডের garments ট্যাব থেকে পরিচালনা করা হয়। যে garment_id নেই, অন্য অ্যাকাউন্টের, বা মুছে ফেলা হয়েছে সেটি 404 garment_not_found দেয়; যেটি এখনো প্রস্তুত হচ্ছে সেটি দেয় 409 garment_not_ready — প্রস্তুত হলে হুবহু একই রিকোয়েস্ট আবার পাঠান।
ফাইল আপলোড
ছবির কাঁচা বাইট আপনার হাতেই থাকলে — যেমন আপনার ব্যবহারকারীর সদ্য আপলোড করা ফাইল — এবং শুধু এই API-কে একটি URL ধরিয়ে দেওয়ার জন্য সেটি কোথাও পাবলিকলি হোস্ট করতে না চাইলে JSON এন্ডপয়েন্টের বদলে POST /v1/tryon/upload ব্যবহার করুন। জব মডেল একই রকম অ্যাসিনক্রোনাস: এটিও 202 সহ একটি জব আইডি ফেরত দেয়।
হেডার:
POST /v1/tryon/upload
Content-Type: multipart/form-data
Authorization: Bearer <your-api-key>| ফিল্ড | টাইপ | আবশ্যক | বিবরণ |
|---|---|---|---|
model_name | text | না | JSON এন্ডপয়েন্টের মতোই। ডিফল্ট tryon-v1.6। |
model_image | file | শর্তসাপেক্ষ | model_image / model_image_url-এর ঠিক একটি দিতে হবে। ব্যক্তি/মডেলের ছবি, সরাসরি আপলোড করা। |
model_image_url | text | শর্তসাপেক্ষ | model_image / model_image_url-এর ঠিক একটি দিতে হবে। ব্যক্তি/মডেলের ছবির URL। |
garment_image | file | শর্তসাপেক্ষ | garment_image / garment_image_url / garment_id-এর ঠিক একটি দিতে হবে। পোশাকের রেফারেন্স ছবি, সরাসরি আপলোড করা। |
garment_image_url | text | শর্তসাপেক্ষ | garment_image / garment_image_url / garment_id-এর ঠিক একটি দিতে হবে। পোশাকের রেফারেন্স ছবির URL। |
garment_id | text | শর্তসাপেক্ষ | garment_image / garment_image_url / garment_id-এর ঠিক একটি দিতে হবে। ড্যাশবোর্ড থেকে নিবন্ধন করা গার্মেন্ট প্রিসেটের আইডি। |
callback_url | text | না | JSON এন্ডপয়েন্টের মতোই। |
মডেলের ছবি এবং পোশাকের ইনপুট আলাদাভাবে নির্ধারিত হয় — একই রিকোয়েস্টে আপনি একটিকে ফাইল হিসেবে আপলোড করে অন্যটিকে URL হিসেবে দিতে পারেন; যেমন নতুন একটি মডেল ছবি আপলোড করে আগে থেকে হোস্ট করা পোশাকের ছবি বা একটি garment_id পুনরায় ব্যবহার করা। একই ইনপুটের একাধিক রূপ দিলে, বা কোনোটিই না দিলে 422 validation_error ফেরত আসে।
ছবির শর্ত
মডেলের ছবি ও পোশাকের ছবি — দুটিকেই নিচের সবগুলো শর্ত পূরণ করতে হবে। URL-ভিত্তিক ইনপুট যাচাই হয় জবটি গৃহীত হওয়ার পরে, তাই ব্যর্থতা সাবমিটের সময় HTTP এরর হিসেবে না এসে জবের উপর status: "failed" হিসেবে দেখা দেয়। /v1/tryon/upload-এ আপলোড করা ফাইল এর ব্যতিক্রম: বাইটগুলো হাতেই থাকায় যাচাই সস্তা, তাই সেটি সাথে সাথেই 400 invalid_image_upload দিয়ে বাতিল হয়।
| শর্ত | সীমা / নিয়ম |
|---|---|
| স্কিম | শুধু http বা https |
| ফরম্যাট | PNG, JPEG, WebP, বা GIF |
| Content-Type | সার্ভারকে অবশ্যই একটি image/* কনটেন্ট টাইপ পেতে হবে |
| সর্বোচ্চ আকার | প্রতি ছবিতে ১০ MB |
| অ্যাক্সেসযোগ্যতা | URL-কে ১০ সেকেন্ডের মধ্যে HTTP 200 ফেরত দিতে হবে |
| রিডাইরেক্ট | সর্বোচ্চ ২টি রিডাইরেক্ট অনুসরণ করা হয় |
| হোস্ট | অবশ্যই একটি সর্বজনীন IP ঠিকানায় রিজলভ হতে হবে |
অ্যাক্সেসযোগ্যতা, রিডাইরেক্ট ও হোস্ট — এই তিনটি শর্ত কেবল URL-ভিত্তিক পদ্ধতিতে প্রযোজ্য, অর্থাৎ সরাসরি পাঠানো URL অথবা আপলোড এন্ডপয়েন্টে model_image_url/garment_image_url-এ দেওয়া URL। model_image/garment_image দিয়ে আপলোড করা ফাইলে নেটওয়ার্ক থেকে কিছু আনার ধাপই থাকে না, তবে ফরম্যাট, Content-Type ও সর্বোচ্চ আকার তখনও যাচাই করা হয়।
169.254.169.254), 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, ::1 এবং fc00::/7 রয়েছে। প্রতিটি রিডাইরেক্ট ধাপ আবার যাচাই করা হয়। সর্বজনীন ইমেজ হোস্টিং ব্যবহার করুন (আপনার নিজের CDN, পাবলিক রিড সহ অবজেক্ট স্টোরেজ ইত্যাদি)। একই নিয়ম আপনার callback_url-এর ক্ষেত্রেও প্রযোজ্য।আউটপুটের aspect ratio
আউটপুটের aspect ratio model_image-এর সাথে মেলে, নিকটতম সমর্থিত অনুপাতে বসিয়ে নেওয়া হয় (যেমন 1:1, 16:9, 9:16, 4:3, 3:4, 4:5)। ফ্রেমিং নিশ্চিত রাখতে পাঠানোর আগেই ব্যক্তির ছবিটি আপনার কাঙ্ক্ষিত অনুপাতে ক্রপ করে নিন।
ভালো ফলের জন্য পরামর্শ
- ব্যক্তির একটি পরিষ্কার, ভালো আলোর, সামনের দিক থেকে তোলা ছবি ব্যবহার করুন।
- পোশাকের একটি পরিষ্কার রেফারেন্স ব্যবহার করুন (শুইয়ে রাখা বা কারও পরনে) যেখানে জিনিসটি পুরোপুরি দেখা যায়। পোশাকের ব্যাকগ্রাউন্ড বাদ দেওয়া হয়, তাই সেটি সাদামাটা হওয়ার দরকার নেই।
- পোশাকের ছবিতে যদি অ্যাক্সেসরিজ থাকে (জুতা, টুপি, বেল্ট, চশমা, ব্যাগ, গয়না), সেগুলোও বসে যেতে পারে।
- পুরো শরীরের পোশাক (গাউন/জাম্পস্যুট) ওপর ও নিচ দুটোই বদলে দেয়; "টপ" যথাযথভাবে স্তরে বসে।
সাবমিট রেসপন্স
গৃহীত → 202 Accepted
{
"id": "tryon_V1StGXR8Z5jdHi6BmyT8x",
"status": "queued",
"model_name": "tryon-v1.6",
"created_at": "2026-08-09T12:00:00Z",
"updated_at": "2026-08-09T12:00:00Z",
"output": null,
"error": null
}| ফিল্ড | বিবরণ |
|---|---|
id | জবের অনন্য আইডি (tryon_…)। GET /v1/tryon/jobs/{id} পোল করতে এটি ব্যবহার করুন। জব শেষ হলে এটিই আউটপুট ফাইলের নামও। |
status | queued, processing, completed, বা failed-এর একটি। |
model_name | আপনার পাঠানো মডেল আইডেন্টিফায়ার, নয়তো ডিফল্টটি। |
created_at / updated_at | UTC টাইমস্ট্যাম্প (ISO 8601)। |
output | জব completed না হওয়া পর্যন্ত null, তারপর { "image_url": "…" }। |
error | status failed না হলে null, নয়তো { "code", "message" }। |
202-এর মানে জবটি প্রসেসিংয়ের জন্য গৃহীত হয়েছে, সফল হবেই তা নয় — আসল ফল জানতে পোলিং বা কলব্যাকের মাধ্যমে status/error দেখুন।
X-Request-ID হেডার থাকে — সমস্যা জানানোর সময় সেটি সাথে দিন। চাইলে রিকোয়েস্টে নিজের X-Request-ID সেট করতে পারেন, সেটিই ফেরত আসবে।ফলাফলের জন্য পোলিং
এটি সাবমিট রেসপন্সের হুবহু একই আকারের এনভেলপ ফেরত দেয়, জবের বর্তমান অবস্থা অনুযায়ী হালনাগাদ করা।
শেষ হওয়া একটি জব:
{
"id": "tryon_V1StGXR8Z5jdHi6BmyT8x",
"status": "completed",
"model_name": "tryon-v1.6",
"created_at": "2026-08-09T12:00:00Z",
"updated_at": "2026-08-09T12:00:15Z",
"output": {
"image_url": "https://pub-xxxx.r2.dev/outputs/tryon_V1StGXR8Z5jdHi6BmyT8x.png"
},
"error": null
}| স্ট্যাটাস | যার মানে |
|---|---|
queued | গৃহীত, ওয়ার্কারের অপেক্ষায়। একটু পরে আবার পোল করুন। |
processing | জেনারেশন চলছে। একটু পরে আবার পোল করুন। |
completed | হয়ে গেছে — output.image_url বসে গেছে। |
failed | কেন হয়নি তা error.code / error.message বলে দেয়। এরর অংশের জব-লেভেল টেবিলটি দেখুন। |
- ১–৩ সেকেন্ড পর পর পোল করা যুক্তিসঙ্গত। এই এন্ডপয়েন্টে সাবমিশনের রেট লিমিট প্রযোজ্য নয়।
- আপনার নয় এমন বা অস্তিত্বহীন জব আইডি — দুই ক্ষেত্রেই
404 job_not_foundফেরত আসে; কোনো জব আইডি অন্য কারও কিনা তা আমরা জানাই না।
কলব্যাক
ঐচ্ছিক। সাবমিটের সময় callback_url দিলে, জব চূড়ান্ত অবস্থায় (completed বা failed) পৌঁছানোমাত্র আমরা উপরের সেই একই এনভেলপ ওই URL-এ POST করি।
POST <your callback_url>
Content-Type: application/json
{ "id": "tryon_...", "status": "completed", "output": {...}, "error": null, ... }- সাইন করা নয়। এটি সুবিধার জন্য পাঠানো একটি বার্তা, সত্যের উৎস নয়। আপনার
callback_urlকেউ জেনে ফেললে সে সেখানে ভুয়া পেলোডও POST করতে পারে। - ব্যাকঅফসহ পুনরায় চেষ্টা করা হয় — টাইমআউট, সংযোগ ত্রুটি,
5xxবা429-এর ক্ষেত্রে, একটি নির্দিষ্ট সংখ্যক চেষ্টা পর্যন্ত। আপনার এন্ডপয়েন্ট থেকে4xx(429ছাড়া) এলে সেটিকে স্থায়ী ধরা হয় — যে URL পেলোড ফিরিয়ে দিচ্ছে সেখানে আমরা বারবার চেষ্টা করি না। - ডেলিভারির নিশ্চয়তা নেই। পুরো রিট্রাই সময়টা জুড়ে আপনার এন্ডপয়েন্ট বন্ধ থাকলে কলব্যাকটি বাদ পড়ে যায়। পোলিংই নির্ভরযোগ্য বিকল্প হিসেবে থেকে যায় — এ কারণেই
callback_urlদিলেও পোলিং কখনো বন্ধ করা হয় না। - দ্রুত
2xxফেরত দিন। ধীর এন্ডপয়েন্টের ক্ষেত্রে ডেলিভারির চেষ্টাটিকেই টাইমআউট ধরে আবার পাঠানো হতে পারে।
GET /v1/tryon/jobs/{id} কল করে ফলাফল নিশ্চিত করুন — ওটি আপনার API Key দিয়ে অথেন্টিকেটেড।এরর
সব এরর একই এনভেলপে আসে:
{ "error": { "code": "invalid_api_key", "message": "Invalid API key." } }POST /v1/tryon-এ ভ্যালিডেশন এররে (422) অতিরিক্তভাবে একটি details অ্যারে থাকে, যা বলে দেয় কোন ফিল্ডগুলো ব্যর্থ হয়েছে। POST /v1/tryon/upload-এ ফাইল বনাম URL-এর ঠিক-একটি যাচাইও validation_error জানায়, তবে details অ্যারে ছাড়া — কোন ফিল্ডটি বাদ পড়েছে বা দুবার এসেছে তা message-এ বলা থাকে।
HTTP-লেভেল এরর
জব তৈরি হওয়ার আগেই, সাথে সাথেই ফেরত আসে।
| HTTP | code | মানে / কারণ |
|---|---|---|
| 401 | missing_api_key | Authorization হেডার নেই বা ভুল ফরম্যাটের। |
| 401 | invalid_api_key | অজানা বা বাতিল করা কী। |
| 402 | insufficient_credits | আপনার অ্যাকাউন্টে কোটাও নেই, ক্রেডিটও নেই। ড্যাশবোর্ড থেকে টপ-আপ করুন বা প্ল্যান নবায়ন করুন। |
| 402 | key_credit_limit_reached | অ্যাকাউন্টে ক্রেডিট থাকা সত্ত্বেও এই কী-টির নিজের ক্রেডিট লিমিট শেষ। কী-টির লিমিট বাড়ান, নয়তো অন্য কী দিয়ে কল করুন। |
| 404 | job_not_found | অজানা জব আইডি, বা অন্য অ্যাকাউন্টের। |
| 404 | garment_not_found | অজানা garment_id, বা অন্য অ্যাকাউন্টের, বা মুছে ফেলা হয়েছে। |
| 409 | garment_not_ready | গার্মেন্ট প্রিসেটটি আছে কিন্তু এখনো প্রস্তুত হচ্ছে, বা শেষবার প্রস্তুত করতে গিয়ে ব্যর্থ হয়েছে। প্রস্তুত হলে হুবহু একই রিকোয়েস্ট আবার পাঠান। |
| 422 | validation_error | রিকোয়েস্ট বডি স্কিমা ভ্যালিডেশনে ব্যর্থ, অথবা — আপলোড এন্ডপয়েন্টে — একটি ছবির ফাইল ও তার URL সংস্করণ দুটোই দেওয়া হয়েছে বা কোনোটিই দেওয়া হয়নি। |
| 422 | invalid_callback_url | callback_url ব্যবহারযোগ্য সর্বজনীন http/https URL নয়। |
| 400 | invalid_image_upload | আপলোড করা ফাইলটি (শুধু আপলোড এন্ডপয়েন্টে) অবৈধ — ভুল টাইপ, বেশি বড়, নষ্ট, বা পড়া যাচ্ছে না। বাইটগুলো হাতেই থাকায় সাথে সাথেই যাচাই করা হয়। |
| 429 | rate_limited | সাবমিশনে প্রতি-কী রেট লিমিট ছাড়িয়ে গেছে। সাথে একটি Retry-After হেডার থাকে। |
| 503 | queue_unavailable | সাময়িক — জব কিউতে পৌঁছানো যায়নি। সাথে একটি Retry-After হেডার থাকে; সাবমিশন আবার পাঠানো নিরাপদ। |
| 500 | internal_error | অপ্রত্যাশিত সার্ভার ত্রুটি। |
জব-লেভেল এরর
এগুলো HTTP স্ট্যাটাস নয়। পোলিং বা আপনার কলব্যাকের মাধ্যমে এগুলো জবের উপর status: "failed" হিসেবে আসে, কোডটি থাকে error.code-এ।
| error.code | মানে / কারণ |
|---|---|
image_fetch_failed | কোনো ইনপুট ছবির URL আনা বা যাচাই করা যায়নি — ভুল URL, বেশি বড়, ভুল টাইপ, নিষিদ্ধ হোস্ট, টাইমআউট, বা 200 ছাড়া অন্য কিছু। |
image_processing_failed | ছবিটি আনা গেছে কিন্তু ডিকোড বা স্বাভাবিক করা যায়নি। |
generation_failed | মডেল কোনো ছবি তৈরি করতে পারেনি। |
content_blocked | নিরাপত্তা ফিল্টারে জেনারেশন আটকে গেছে। |
upstream_unavailable | পুরো রিট্রাই সময়জুড়ে আপস্ট্রিম জেনারেশন সরবরাহকারীর নাগাল পাওয়া যায়নি। |
internal_error | প্রসেসিংয়ের সময় অপ্রত্যাশিত সার্ভার ত্রুটি। |
কীভাবে সামলাবেন
429— রেসপন্সেরRetry-Afterহেডার (সেকেন্ডে) পড়ে অপেক্ষা করে তারপর সাবমিশন আবার চেষ্টা করুন।503 queue_unavailable— সাময়িক; ব্যাকঅফসহ সাবমিশন আবার পাঠান।generation_failed/content_blocked(জবের উপর) — সাধারণত ইনপুট-সংক্রান্ত। ব্যক্তির আরও পরিষ্কার ছবি বা অন্য পোশাকের ছবি দিন;content_blocked-এর ক্ষেত্রে হুবহু একই রিকোয়েস্ট আবার পাঠিয়ে খুব একটা লাভ হয় না।image_fetch_failed(জবের উপর) — যাচাই করুন URL-টি সর্বজনীন কিনা, ছবি ফেরত দেয় কিনা, ১০ MB-এর কম কিনা, এবং সর্বজনীন হোস্টে রিজলভ হয় কিনা।invalid_image_upload(শুধু আপলোড এন্ডপয়েন্টে) — যাচাই করুন আপলোড করা ফাইলটি ১০ MB-এর কম PNG/JPEG/WebP/GIF এবং নষ্ট নয়।internal_error/upstream_unavailable— সাময়িক; ব্যাকঅফসহ আবার পাঠানো নিরাপদ।
রেট লিমিট
- শুধু জব সাবমিশনে প্রযোজ্য (
POST /v1/tryonওPOST /v1/tryon/upload) —GET /v1/tryon/jobs/{id}পোল করায় রেট লিমিট নেই। - ডিফল্ট: প্রতি API Key-তে মিনিটে ৬০টি রিকোয়েস্ট (কিছু কী-তে কাস্টম লিমিট থাকতে পারে)।
- একটি রোলিং ৬০-সেকেন্ড উইন্ডো দিয়ে প্রয়োগ করা হয়।
- এটি অতিক্রম করলে
429ফেরত দেয় সাথে একটিRetry-Afterহেডার যা আপনাকে কত সেকেন্ড অপেক্ষা করতে হবে তা জানায়।
উদাহরণ
নিচের প্রতিটি উদাহরণ একটি জব পাঠায়, তারপর ফলাফল সংগ্রহ করে। জেনারেশনের অপেক্ষায় কোনো সংযোগ খোলা রাখা হয় না।
পাঠান, তারপর পোল করুন
সাধারণ ইন্টিগ্রেশন: জবটি POST করুন, তারপর queued/processing অবস্থা ছাড়ানো পর্যন্ত জব এন্ডপয়েন্ট পোল করুন।
# 1. Submit
resp=$(curl -s -X POST https://api.benitoai.com/v1/tryon \
-H "Authorization: Bearer bnto_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"model_name": "tryon-v1.6",
"inputs": {
"model_image": "https://example.com/person.jpg",
"garment_image": "https://example.com/garment.jpg"
}
}')
job_id=$(echo "$resp" | jq -r .id)
# 2. Poll until done
until [ "$(curl -s https://api.benitoai.com/v1/tryon/jobs/$job_id \
-H "Authorization: Bearer bnto_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" | jq -r .status)" != "queued" ]; do
sleep 2
done
curl -s https://api.benitoai.com/v1/tryon/jobs/$job_id \
-H "Authorization: Bearer bnto_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" | jqপোলিংয়ের বদলে কলব্যাক নেওয়া
সাবমিটের সময় একটি callback_url দিন, শেষ হওয়া জবটি আমরা সেখানে POST করব। পেলোডকে বিশ্বাস করার আগে একটি GET দিয়ে নিশ্চিত হয়ে নিন — কলব্যাক সাইন করা নয়।
app.post("/webhooks/tryon", express.json(), (req, res) => {
const job = req.body;
// Always confirm via GET /v1/tryon/jobs/{id} before trusting this —
// this endpoint is unsigned.
if (job.status === "completed") {
console.log("Result:", job.output.image_url);
} else if (job.status === "failed") {
console.error("Failed:", job.error);
}
res.sendStatus(200);
});সরাসরি ফাইল আপলোড
অথেন্টিকেশনের নিয়ম একই; শুধু বডির গড়ন বদলায়। এই উদাহরণগুলো মডেলের ছবি আপলোড করে এবং পোশাকের ছবি URL দিয়ে পুনরায় ব্যবহার করে, মিশ্র ক্ষেত্রটি দেখানোর জন্য — দুটি ইনপুটের যেকোনোটিই আলাদাভাবে ফাইল বা URL হতে পারে।
curl -X POST https://api.benitoai.com/v1/tryon/upload \
-H "Authorization: Bearer bnto_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-F "model_name=tryon-v1.6" \
-F "model_image=@person.jpg" \
-F "garment_image_url=https://example.com/garment.jpg"অন্যান্য এন্ডপয়েন্ট
| এন্ডপয়েন্ট | কাজ |
|---|---|
GET /health | লাইভনেস চেক। সুস্থ থাকলে 200 সহ {"status":"ok","mongo":true,"rabbitmq":true} ফেরত দেয়, নয়তো 503। অথেন্টিকেশন লাগে না। |
GET /docs | ব্রাউজারে API ঘেঁটে দেখা ও পরীক্ষা করার জন্য ইন্টার্যাক্টিভ Swagger/OpenAPI UI। |
কল করার আগে দ্রুত চেকলিস্ট
- ☐
Authorizationহেডারে Bearer API Key বসানো আছে। - ☐ ছবির URL সর্বজনীন
http/httpsএবং PNG/JPEG/WebP/GIF ফেরত দেয় — অথবা আপনি ফাইলগুলো সরাসরি আপলোড করছেন। - ☐ প্রতিটি ছবি ১০ MB-এর কম এবং ১০ সেকেন্ডের মধ্যে লোড হয়।
- ☐ ব্যক্তির ছবি আপনার কাঙ্ক্ষিত আউটপুট aspect ratio-তে ক্রপ করা।
- ☐ আপনার ইন্টিগ্রেশন ব্লকিং রেসপন্সের আশা না করে
GET /v1/tryon/jobs/{id}পোল করে এবং/অথবাcallback_urlডেলিভারি সামলায়। - ☐ সাবমিশনে
429ও503-এর জন্যRetry-Afterমেনে রিট্রাই/ব্যাকঅফ লজিক আছে।
শুরু করতে প্রস্তুত?
ড্যাশবোর্ড থেকে একটি API Key তৈরি করুন এবং প্রথম কলটি করে ফেলুন।