API রেফারেন্স

Virtual Try-On API

একজন ব্যক্তির ছবি এবং একটি পোশাকের ছবি পাঠান — সেই ব্যক্তি সেই পোশাক পরে আছেন এমন একটি ফটোরিয়েলিস্টিক ছবি ফেরত পান। একটি জব পাঠান, তারপর ফলাফলের জন্য পোল করুন অথবা আমাদের কলব্যাক নিন।

POSThttps://api.benitoai.com/v1/tryon
POSThttps://api.benitoai.com/v1/tryon/upload
GEThttps://api.benitoai.com/v1/tryon/jobs/{id}

গুরুত্বপূর্ণ পরিবর্তন

এই API আগে পুরোপুরি সিঙ্ক্রোনাস ছিল — একটি রিকোয়েস্ট, একটি ব্লকিং রেসপন্স, যার সাথেই তৈরি হওয়া ছবি আসত। এখন এটি অ্যাসিনক্রোনাস। POST /v1/tryon (এবং /upload) সাথে সাথেই 202 সহ একটি জব আইডি ফেরত দেয়; ফলাফল পেতে হয় GET /v1/tryon/jobs/{id} পোল করে, নয়তো একটি callback_url দিয়ে। আপনি যদি এই ডকুমেন্টেশনের পুরোনো সংস্করণ ধরে ইন্টিগ্রেট করে থাকেন, সেটি হালনাগাদ করুন — আগের এক-কলেই-সব পদ্ধতি আর কাজ করে না।

AI কোডিং এজেন্ট ব্যবহার করছেন?

প্রতিটি এন্ডপয়েন্ট, ফিল্ড, জব স্ট্যাটাস ও এরর কোডসহ সংক্ষিপ্ত markdown স্পেক ডাউনলোড করুন — অথবা সরাসরি চ্যাটে কপি করে নিন। ফাইলটি শুধু ইংরেজিতে।

LLM-এর জন্য নির্দেশনা

ড্যাশবোর্ড থেকে API Key তৈরি করুন

আপনার BenitoAI ড্যাশবোর্ডের API keys ট্যাব খুলে কয়েক ক্লিকেই একটি কী তৈরি করে নিন। কী শুধু একবারই দেখানো হয়, তৈরির সময় — সেটি সরাসরি আপনার সার্ভারের সিক্রেট স্টোরে কপি করে রাখুন। চাইলে সেখান থেকেই আলাদা কোনো কী-এর জন্য নিজস্ব ক্রেডিট লিমিটও বেঁধে দিতে পারেন।

01

মূল ধারণা

প্রথমে এগুলো পড়ুন — এগুলো আপনার ইন্টিগ্রেশনের ধরন নির্ধারণ করে।

  • অ্যাসিনক্রোনাস জব মডেল। রিকোয়েস্ট পাঠালে সাথে সাথেই একটি জব আইডি ফেরত আসে — জেনারেশন শেষ হওয়ার জন্য এটি অপেক্ষা করে না। এরপর আপনি হয় GET /v1/tryon/jobs/{id} পোল করবেন যতক্ষণ না status completed (বা failed) হয়, নয়তো একটি callback_url দেবেন এবং কাজ শেষ হলে আমরা সেখানে জবটি POST করব। দুটি ব্যবস্থাই সবসময় খোলা থাকে — callback_url দিয়েছেন বলে পোলিং বন্ধ হয়ে যায় না।
  • জেনারেশনে প্রায় ১০–৬০ সেকেন্ড লাগে জব প্রসেস হওয়া শুরু করার পর, সাথে কিউতে অপেক্ষার সময় যোগ হতে পারে। তাই একটি দীর্ঘ সংযোগ ধরে রাখার বদলে পরে ফিরে এসে খোঁজ নেওয়ার কথা মাথায় রেখে ইন্টিগ্রেশন সাজান (১–৩ সেকেন্ড পর পর পোল করা যুক্তিসঙ্গত)।
  • ছবি দেওয়ার দুটি উপায়। POST /v1/tryon JSON নেয়, যেখানে ছবির URL http/https-এ সর্বজনীনভাবে অ্যাক্সেসযোগ্য হতে হয় — সার্ভার নিজেই সেগুলো ডাউনলোড করে। POST /v1/tryon/upload নেয় multipart/form-data, যাতে আপনি সরাসরি ফাইলটাই আপলোড করতে পারেন — শুধু এই API যেন ছবিটি ডাউনলোড করতে পারে সেজন্য আগে কোথাও পাবলিকলি হোস্ট করার ঝামেলা বাঁচে।
  • আউটপুট একটি হোস্টেড PNG URL। API কখনো base64 ফেরত দেয় না — আপনি তৈরি হওয়া .png-এর একটি URL পান।
02

অথেন্টিকেশন

প্রতিটি রিকোয়েস্টে Authorization হেডারে একটি Bearer API Key প্রয়োজন:

http
Authorization: Bearer bnto_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
  • কী-এর শুরুতে থাকে bnto_live_, তারপর একটি এলোমেলো স্ট্রিং।
  • কী শুধুমাত্র একবার, তৈরির সময় দেখানো হয় — আপনারটি নিরাপদে সংরক্ষণ করুন।
  • অনুপস্থিত, ভুল ফরম্যাটের, বাতিল করা, বা অজানা কী 401 ফেরত দেয়।
  • কী-কে একটি গোপনীয় তথ্য হিসেবে বিবেচনা করুন: এটি কখনো ক্লায়েন্ট-সাইড/ব্রাউজার কোডে এম্বেড করবেন না বা সোর্স কন্ট্রোলে কমিট করবেন না। আপনার ব্যাকএন্ড থেকে API কল করুন।
এখনো কী নেই? ড্যাশবোর্ডের API keys ট্যাব থেকে একটি তৈরি করে নিন, অথবা সাহায্য দরকার হলে আমাদের সাথে যোগাযোগ করুন
03

ক্রেডিট ও কোটা

গৃহীত প্রতিটি try-on-এর খরচ একটি ক্রেডিট, যা কাটা হয় সাবমিট করার সময় — জব শেষ হওয়ার সময় নয়। কোনো জব failed হলে সেটি স্বয়ংক্রিয়ভাবে ফেরত দেওয়া হয়, ফলে আপনি কেবল সত্যিই পাওয়া জেনারেশনের জন্যই টাকা দেন। এই খরচ মেটায় দুটি হিসাব, এই ক্রমে:

  1. প্ল্যান কোটা — আপনার মাসিক প্ল্যানে অন্তর্ভুক্ত try-on সংখ্যা। প্রতি বিলিং সাইকেলে রিসেট হয়; অব্যবহৃত কোটা পরের মাসে যায় না, এবং সাইকেল শেষ হওয়ামাত্র সেটি আর খরচ করা যায় না।
  2. কেনা ক্রেডিট — আলাদাভাবে কেনা টপ-আপ। এগুলোর মেয়াদ কখনো শেষ হয় না এবং সাবস্ক্রিপশন বন্ধ হয়ে গেলেও থেকে যায়। কোটা ফুরিয়ে গেলে অতিরিক্ত ব্যবহারের খরচ এগুলো থেকেই কাটে।
এ দুটি আলাদা সংখ্যা, এবং usage ট্যাবে এগুলো আলাদা করেই দেখানো হয়। নিজের UI-তে এগুলো যোগ করে একটি সংখ্যা বানাবেন না: দুটির খরচের নিয়ম আলাদা, তাই মিলিয়ে দেখানো সংখ্যাটি সাইকেল শেষ হয়ে গেলে বাস্তবে যা ব্যবহার করা যাবে তার চেয়ে বেশি দেখাবে।

ক্রেডিট আপনার অ্যাকাউন্টের, কোনো নির্দিষ্ট কী-এর নয়। আপনার সব API Key একই পুল থেকে খরচ করে — তিনটি কী দিয়ে দুটি করে try-on চালালে মোট ছয়টি ক্রেডিট খরচ হয়। চাইলে আলাদা কোনো কী-এর জন্য নিজস্ব ক্রেডিট লিমিট বেঁধে দিতে পারেন, যা ঠিক করে দেয় সেই কী শেয়ার করা পুল থেকে সর্বোচ্চ কতটা খরচ করতে পারবে। এটি একটি সর্বোচ্চ সীমা, আলাদা বরাদ্দ নয় — এতে খরচের ক্ষমতা বাড়ে না।

কোনো হিসাবেই যদি কলটির খরচ না মেটে, আপনি 402 insufficient_credits পাবেন এবং কিছুই কিউতে যাবে না। অ্যাকাউন্টে ক্রেডিট থাকা সত্ত্বেও কী-টির নিজের লিমিট শেষ হয়ে গেলে বদলে পাবেন 402 key_credit_limit_reached — একই স্ট্যাটাস, কিন্তু সমাধান ভিন্ন, তাই code দেখে নিন।

04

জব পাঠানো

এন্ডপয়েন্টে একটি JSON বডি পাঠান। রেসপন্স সাথে সাথেই আসে এবং তাতে ছবি থাকে না।

POSThttps://api.benitoai.com/v1/tryon

বডি স্কিমা:

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_namestringনালজিক্যাল মডেল আইডেন্টিফায়ার। ডিফল্ট tryon-v1.6। রেসপন্সে ফেরত আসে।
inputs.model_imageURLহ্যাঁব্যক্তি/মডেলের ছবির সর্বজনীন URL। এই ছবিই আউটপুটের পরিচয়, ভঙ্গি, ব্যাকগ্রাউন্ড ও aspect ratio ঠিক করে।
inputs.garment_imageURLশর্তসাপেক্ষgarment_image / garment_id-এর ঠিক একটি দিতে হবে। পোশাকের ছবির সর্বজনীন URL। শুধু কাপড়, কাট ও রঙের রেফারেন্স হিসেবে ব্যবহৃত হয় — এর ব্যাকগ্রাউন্ড ধরা হয় না।
inputs.garment_idstringশর্তসাপেক্ষgarment_image / garment_id-এর ঠিক একটি দিতে হবে। ড্যাশবোর্ড থেকে নিবন্ধন করা একটি গার্মেন্ট প্রিসেটের আইডি, যেমন grm_V1StGXR8Z5jdHi6BmyT। নিচের গার্মেন্ট প্রিসেট অংশ দেখুন।
callback_urlURLনাদিলে, জব শেষ বা ব্যর্থ হওয়ামাত্র আমরা সেটির এনভেলপ এখানে POST করি। কলব্যাক অংশ দেখুন। যেভাবেই হোক পোলিং খোলা থাকে।

সফলভাবে পাঠাতে পারলে 202 সহ একটি জব আইডি ফেরত আসে — নিচের সাবমিট রেসপন্স দেখুন, তারপর ফলাফলের জন্য পোলিং

ধারণাগতভাবে ক্রম গুরুত্বপূর্ণ: model_image হলো ব্যক্তি; garment_image হলো পোশাক। ব্যক্তির মুখ, শরীর, ভঙ্গি ও ব্যাকগ্রাউন্ড অক্ষত থাকে; পোশাকটি তার গায়ে বসিয়ে দেওয়া হয়।
05

গার্মেন্ট প্রিসেট

বেশিরভাগ ইন্টিগ্রেশনে একই পোশাকের ছবি বারবার পাঠানো হয়, শুধু ব্যক্তির ছবি প্রতিবার বদলায়। এমন ক্ষেত্রে প্রতিবার URL পাঠানোর বদলে প্রতিটি পোশাক ড্যাশবোর্ডে একবার নিবন্ধন করে নিন: আমরা আগেই ছবিটি পরিষ্কার করে রাখি — পোশাকটিকে সোজাসুজি করে একটি সাদামাটা ব্যাকগ্রাউন্ডে আলাদা করে নেওয়া হয় — সেটি সংরক্ষণ করি, এবং আপনাকে একটি স্থায়ী garment_id দিই।

  • ফল ভালো হয় — মডেল তখন এলোমেলো ব্যাকগ্রাউন্ডে অন্য কারও পরনে থাকা ছবির বদলে একটি পরিষ্কার পোশাকের রেফারেন্স ধরে কাজ করে।
  • শুরু হয় দ্রুত — প্রতিবার পোশাকের ছবি নামানো ও প্রস্তুত করার ধাপটি বাদ যায়, কারণ সেটি আগে থেকেই সংরক্ষিত ও তৈরি থাকে।

একই রিকোয়েস্ট, URL-এর বদলে প্রিসেট দিয়ে:

json
{
  "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 — প্রস্তুত হলে হুবহু একই রিকোয়েস্ট আবার পাঠান।

06

ফাইল আপলোড

ছবির কাঁচা বাইট আপনার হাতেই থাকলে — যেমন আপনার ব্যবহারকারীর সদ্য আপলোড করা ফাইল — এবং শুধু এই API-কে একটি URL ধরিয়ে দেওয়ার জন্য সেটি কোথাও পাবলিকলি হোস্ট করতে না চাইলে JSON এন্ডপয়েন্টের বদলে POST /v1/tryon/upload ব্যবহার করুন। জব মডেল একই রকম অ্যাসিনক্রোনাস: এটিও 202 সহ একটি জব আইডি ফেরত দেয়।

POSThttps://api.benitoai.com/v1/tryon/upload

হেডার:

http
POST /v1/tryon/upload
Content-Type: multipart/form-data
Authorization: Bearer <your-api-key>
ফিল্ডটাইপআবশ্যকবিবরণ
model_nametextনাJSON এন্ডপয়েন্টের মতোই। ডিফল্ট tryon-v1.6
model_imagefileশর্তসাপেক্ষmodel_image / model_image_url-এর ঠিক একটি দিতে হবে। ব্যক্তি/মডেলের ছবি, সরাসরি আপলোড করা।
model_image_urltextশর্তসাপেক্ষmodel_image / model_image_url-এর ঠিক একটি দিতে হবে। ব্যক্তি/মডেলের ছবির URL।
garment_imagefileশর্তসাপেক্ষgarment_image / garment_image_url / garment_id-এর ঠিক একটি দিতে হবে। পোশাকের রেফারেন্স ছবি, সরাসরি আপলোড করা।
garment_image_urltextশর্তসাপেক্ষgarment_image / garment_image_url / garment_id-এর ঠিক একটি দিতে হবে। পোশাকের রেফারেন্স ছবির URL।
garment_idtextশর্তসাপেক্ষgarment_image / garment_image_url / garment_id-এর ঠিক একটি দিতে হবে। ড্যাশবোর্ড থেকে নিবন্ধন করা গার্মেন্ট প্রিসেটের আইডি।
callback_urltextনাJSON এন্ডপয়েন্টের মতোই।

মডেলের ছবি এবং পোশাকের ইনপুট আলাদাভাবে নির্ধারিত হয় — একই রিকোয়েস্টে আপনি একটিকে ফাইল হিসেবে আপলোড করে অন্যটিকে URL হিসেবে দিতে পারেন; যেমন নতুন একটি মডেল ছবি আপলোড করে আগে থেকে হোস্ট করা পোশাকের ছবি বা একটি garment_id পুনরায় ব্যবহার করা। একই ইনপুটের একাধিক রূপ দিলে, বা কোনোটিই না দিলে 422 validation_error ফেরত আসে।

চালিয়ে দেখার মতো multipart উদাহরণ নিচের উদাহরণ অংশে আছে।

07

ছবির শর্ত

মডেলের ছবি ও পোশাকের ছবি — দুটিকেই নিচের সবগুলো শর্ত পূরণ করতে হবে। 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 ও সর্বোচ্চ আকার তখনও যাচাই করা হয়।

SSRF সুরক্ষা: যেসব URL প্রাইভেট, লুপব্যাক, লিংক-লোকাল, সংরক্ষিত, মাল্টিকাস্ট বা অনির্দিষ্ট ঠিকানায় রিজলভ হয় সেগুলো বাতিল করা হয় — এর মধ্যে ক্লাউড মেটাডেটা এন্ডপয়েন্ট (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)। ফ্রেমিং নিশ্চিত রাখতে পাঠানোর আগেই ব্যক্তির ছবিটি আপনার কাঙ্ক্ষিত অনুপাতে ক্রপ করে নিন।

ভালো ফলের জন্য পরামর্শ

  • ব্যক্তির একটি পরিষ্কার, ভালো আলোর, সামনের দিক থেকে তোলা ছবি ব্যবহার করুন।
  • পোশাকের একটি পরিষ্কার রেফারেন্স ব্যবহার করুন (শুইয়ে রাখা বা কারও পরনে) যেখানে জিনিসটি পুরোপুরি দেখা যায়। পোশাকের ব্যাকগ্রাউন্ড বাদ দেওয়া হয়, তাই সেটি সাদামাটা হওয়ার দরকার নেই।
  • পোশাকের ছবিতে যদি অ্যাক্সেসরিজ থাকে (জুতা, টুপি, বেল্ট, চশমা, ব্যাগ, গয়না), সেগুলোও বসে যেতে পারে।
  • পুরো শরীরের পোশাক (গাউন/জাম্পস্যুট) ওপর ও নিচ দুটোই বদলে দেয়; "টপ" যথাযথভাবে স্তরে বসে।
08

সাবমিট রেসপন্স

গৃহীত → 202 Accepted

json
{
  "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} পোল করতে এটি ব্যবহার করুন। জব শেষ হলে এটিই আউটপুট ফাইলের নামও।
statusqueued, processing, completed, বা failed-এর একটি।
model_nameআপনার পাঠানো মডেল আইডেন্টিফায়ার, নয়তো ডিফল্টটি।
created_at / updated_atUTC টাইমস্ট্যাম্প (ISO 8601)।
outputজব completed না হওয়া পর্যন্ত null, তারপর { "image_url": "…" }
errorstatus failed না হলে null, নয়তো { "code", "message" }

202-এর মানে জবটি প্রসেসিংয়ের জন্য গৃহীত হয়েছে, সফল হবেই তা নয় — আসল ফল জানতে পোলিং বা কলব্যাকের মাধ্যমে status/error দেখুন।

প্রতিটি রেসপন্সে একটি X-Request-ID হেডার থাকে — সমস্যা জানানোর সময় সেটি সাথে দিন। চাইলে রিকোয়েস্টে নিজের X-Request-ID সেট করতে পারেন, সেটিই ফেরত আসবে।
09

ফলাফলের জন্য পোলিং

GEThttps://api.benitoai.com/v1/tryon/jobs/{id}

এটি সাবমিট রেসপন্সের হুবহু একই আকারের এনভেলপ ফেরত দেয়, জবের বর্তমান অবস্থা অনুযায়ী হালনাগাদ করা।

শেষ হওয়া একটি জব:

json
{
  "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 ফেরত আসে; কোনো জব আইডি অন্য কারও কিনা তা আমরা জানাই না।
10

কলব্যাক

ঐচ্ছিক। সাবমিটের সময় callback_url দিলে, জব চূড়ান্ত অবস্থায় (completed বা failed) পৌঁছানোমাত্র আমরা উপরের সেই একই এনভেলপ ওই URL-এ POST করি।

http
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 দিয়ে অথেন্টিকেটেড।
11

এরর

সব এরর একই এনভেলপে আসে:

json
{ "error": { "code": "invalid_api_key", "message": "Invalid API key." } }

POST /v1/tryon-এ ভ্যালিডেশন এররে (422) অতিরিক্তভাবে একটি details অ্যারে থাকে, যা বলে দেয় কোন ফিল্ডগুলো ব্যর্থ হয়েছে। POST /v1/tryon/upload-এ ফাইল বনাম URL-এর ঠিক-একটি যাচাইও validation_error জানায়, তবে details অ্যারে ছাড়া — কোন ফিল্ডটি বাদ পড়েছে বা দুবার এসেছে তা message-এ বলা থাকে।

HTTP-লেভেল এরর

জব তৈরি হওয়ার আগেই, সাথে সাথেই ফেরত আসে।

HTTPcodeমানে / কারণ
401missing_api_keyAuthorization হেডার নেই বা ভুল ফরম্যাটের।
401invalid_api_keyঅজানা বা বাতিল করা কী।
402insufficient_creditsআপনার অ্যাকাউন্টে কোটাও নেই, ক্রেডিটও নেই। ড্যাশবোর্ড থেকে টপ-আপ করুন বা প্ল্যান নবায়ন করুন।
402key_credit_limit_reachedঅ্যাকাউন্টে ক্রেডিট থাকা সত্ত্বেও এই কী-টির নিজের ক্রেডিট লিমিট শেষ। কী-টির লিমিট বাড়ান, নয়তো অন্য কী দিয়ে কল করুন।
404job_not_foundঅজানা জব আইডি, বা অন্য অ্যাকাউন্টের।
404garment_not_foundঅজানা garment_id, বা অন্য অ্যাকাউন্টের, বা মুছে ফেলা হয়েছে।
409garment_not_readyগার্মেন্ট প্রিসেটটি আছে কিন্তু এখনো প্রস্তুত হচ্ছে, বা শেষবার প্রস্তুত করতে গিয়ে ব্যর্থ হয়েছে। প্রস্তুত হলে হুবহু একই রিকোয়েস্ট আবার পাঠান।
422validation_errorরিকোয়েস্ট বডি স্কিমা ভ্যালিডেশনে ব্যর্থ, অথবা — আপলোড এন্ডপয়েন্টে — একটি ছবির ফাইল ও তার URL সংস্করণ দুটোই দেওয়া হয়েছে বা কোনোটিই দেওয়া হয়নি।
422invalid_callback_urlcallback_url ব্যবহারযোগ্য সর্বজনীন http/https URL নয়।
400invalid_image_uploadআপলোড করা ফাইলটি (শুধু আপলোড এন্ডপয়েন্টে) অবৈধ — ভুল টাইপ, বেশি বড়, নষ্ট, বা পড়া যাচ্ছে না। বাইটগুলো হাতেই থাকায় সাথে সাথেই যাচাই করা হয়।
429rate_limitedসাবমিশনে প্রতি-কী রেট লিমিট ছাড়িয়ে গেছে। সাথে একটি Retry-After হেডার থাকে।
503queue_unavailableসাময়িক — জব কিউতে পৌঁছানো যায়নি। সাথে একটি Retry-After হেডার থাকে; সাবমিশন আবার পাঠানো নিরাপদ।
500internal_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 — সাময়িক; ব্যাকঅফসহ আবার পাঠানো নিরাপদ।
12

রেট লিমিট

  • শুধু জব সাবমিশনে প্রযোজ্য (POST /v1/tryonPOST /v1/tryon/upload) — GET /v1/tryon/jobs/{id} পোল করায় রেট লিমিট নেই
  • ডিফল্ট: প্রতি API Key-তে মিনিটে ৬০টি রিকোয়েস্ট (কিছু কী-তে কাস্টম লিমিট থাকতে পারে)।
  • একটি রোলিং ৬০-সেকেন্ড উইন্ডো দিয়ে প্রয়োগ করা হয়।
  • এটি অতিক্রম করলে 429 ফেরত দেয় সাথে একটি Retry-After হেডার যা আপনাকে কত সেকেন্ড অপেক্ষা করতে হবে তা জানায়।
13

উদাহরণ

নিচের প্রতিটি উদাহরণ একটি জব পাঠায়, তারপর ফলাফল সংগ্রহ করে। জেনারেশনের অপেক্ষায় কোনো সংযোগ খোলা রাখা হয় না।

পাঠান, তারপর পোল করুন

সাধারণ ইন্টিগ্রেশন: জবটি 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 দিয়ে নিশ্চিত হয়ে নিন — কলব্যাক সাইন করা নয়।

javascript
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"
14

অন্যান্য এন্ডপয়েন্ট

এন্ডপয়েন্টকাজ
GET /healthলাইভনেস চেক। সুস্থ থাকলে 200 সহ {"status":"ok","mongo":true,"rabbitmq":true} ফেরত দেয়, নয়তো 503। অথেন্টিকেশন লাগে না।
GET /docsব্রাউজারে API ঘেঁটে দেখা ও পরীক্ষা করার জন্য ইন্টার‌্যাক্টিভ Swagger/OpenAPI UI।
15

কল করার আগে দ্রুত চেকলিস্ট

  • Authorization হেডারে Bearer API Key বসানো আছে।
  • ☐ ছবির URL সর্বজনীন http/https এবং PNG/JPEG/WebP/GIF ফেরত দেয় — অথবা আপনি ফাইলগুলো সরাসরি আপলোড করছেন।
  • ☐ প্রতিটি ছবি ১০ MB-এর কম এবং ১০ সেকেন্ডের মধ্যে লোড হয়।
  • ☐ ব্যক্তির ছবি আপনার কাঙ্ক্ষিত আউটপুট aspect ratio-তে ক্রপ করা।
  • ☐ আপনার ইন্টিগ্রেশন ব্লকিং রেসপন্সের আশা না করে GET /v1/tryon/jobs/{id} পোল করে এবং/অথবা callback_url ডেলিভারি সামলায়।
  • ☐ সাবমিশনে 429503-এর জন্য Retry-After মেনে রিট্রাই/ব্যাকঅফ লজিক আছে।

শুরু করতে প্রস্তুত?

ড্যাশবোর্ড থেকে একটি API Key তৈরি করুন এবং প্রথম কলটি করে ফেলুন।

ড্যাশবোর্ড খুলুন