মূল কনটেন্টে যান

ডেভেলপার নির্দেশিকা

তৃতীয়-পক্ষ নোটিফিকেশন ইন্টিগ্রেশন

প্রমাণীকরণ, অনুরোধ, idempotency, সীমা, ফলাফল ও নিরাপত্তার বর্তমান চুক্তি।

দ্রুত শুরু

Web Admin থেকে লক্ষ্য কোম্পানির সঙ্গে যুক্ত তৃতীয়-পক্ষ অ্যাপ তৈরি করুন। App ID ও App Secret কপি করুন; চূড়ান্ত ফল দরকার হলে ঐচ্ছিক Callback URL দিন।

Engine ঐচ্ছিক audience-এ নির্বাচিত ব্যবহারকারীদের জন্য রেকর্ড তৈরি করে (default-এ কোম্পানির সব যোগ্য ব্যবহারকারী) এবং শুধু যোগ্য নিবন্ধিত ডিভাইসে সিস্টেম Push পাঠানোর চেষ্টা করে।

Endpoint ও প্রমাণীকরণ

API environment:

প্রতিটি server-to-server JSON request-এ HTTP Basic Authentication ব্যবহার করে Authorization: Basic Base64(KEY:SECRET) পাঠাতে হবে, যেখানে KEY হলো App ID এবং SECRET হলো App Secret:

Endpoint: POST /openapi/v1/notifications।

bash
curl --request POST 'https://<your-engine-host>/openapi/v1/notifications' \
  --header 'Authorization: Basic <Base64(AppID:AppSecret)>' \
  --header 'Content-Type: application/json' \
  --data '{"requestId":"order-20260819-001","title":"অর্ডার সম্পন্ন","body":"আপনার অর্ডার সম্পন্ন হয়েছে।","imageUrls":["https://cdn.example.com/order/001-1.webp","https://cdn.example.com/order/001-2.webp"],"displayFields":[{"label":"দোকানের নাম","value":"শিয়াও হান নুডলস (ওয়াংজিং)"},{"value":"ORD-10086"}],"tags":["সম্পন্ন","প্রধান শাখা"]}'

অনুরোধের চুক্তি

Field সারাংশ

Fieldআবশ্যকTypeঅর্থ
requestIdহ্যাঁstringপ্রেরকের অনন্য request ID ও idempotency key; trim করার পর ফাঁকা হওয়া যাবে না।
titleহ্যাঁstringnotification title; trim করার পর ফাঁকা হওয়া যাবে না।
bodyহ্যাঁstringnotification body; trim করার পর ফাঁকা হওয়া যাবে না।
imageUrlsনাstring[]detail-এ ক্রমানুসারে দেখানো ছবির URL।
displayFieldsনাobject[]detail-এ ক্রমানুসারে দেখানো অতিরিক্ত text field।
tagsনাstring[]শুধু detail-এ ক্রমানুসারে দেখানো plain text tag।
audienceনাobjectusers বা company roles-এ সীমিত করে; না দিলে পুরো eligible company।

ছবি: imageUrls

  • ছবি না থাকলে field বাদ দিন, null বা [] পাঠান; থাকলে 1-9টি URL ক্রমানুসারে পাঠান।
  • প্রতিটি URL trim হয়, অনন্য হতে হয় এবং username/password ছাড়া সম্পূর্ণ HTTPS URL হতে হয়।
  • প্রতিটি URL সর্বোচ্চ 2048 Unicode অক্ষর। একটি অবৈধ URL পুরো অনুরোধ বাতিল করে।
  • Engine URL সংরক্ষণ করে, কিন্তু ছবি আনে, যাচাই করে, proxy বা cache করে না।

Detail field: displayFields

Subfieldআবশ্যকসীমাপ্রদর্শন
labelনাtrim-এর পরে খালি নয়; সর্বোচ্চ 32 Unicode অক্ষরfield name।
valueহ্যাঁtrim-এর পরে খালি নয়; সর্বোচ্চ 256 Unicode অক্ষরfield value।
json
{
  "displayFields": [
    { "label": "দোকান", "value": "Little Han Noodles (Wangjing)" },
    { "value": "ORD-10086" }
  ]
}
  • field বাদ দেওয়া, null বা [] মানে অতিরিক্ত সারি নেই; সর্বোচ্চ 10টি object।
  • label না থাকলে বা null হলে value পূর্ণ-প্রস্থের একক সারি হিসেবে দেখায়।
  • content সব সময় plain text; HTML, Markdown, link, nested data, type বা style সমর্থিত নয়।

বিস্তারিত ট্যাগ tags

  • tag না থাকলে field বাদ দিন, null বা [] পাঠান; থাকলে display order-এ সর্বোচ্চ 8টি string পাঠান।
  • প্রতিটি tag trim হয়ে 1-20 Unicode অক্ষরের হতে হবে। ফাঁকা, non-string, বেশি লম্বা বা trim-এর পরে duplicate হলে পুরো request INVALID_REQUEST হয়।
  • Tag হলো non-interactive plain text; শুধু notification detail-এ দেখায় এবং ক্রম অপরিবর্তিত থাকে।

প্রাপক: audience

typeSelectorID-এর অর্থ
USERSuserIdsকোম্পানি সদস্য ID
ROLESrolesCompanyRole ID; যেকোনো role-এর eligible member পায়।

Web Admin-এর কোম্পানি সদস্য তালিকা থেকে কোম্পানি সদস্য ID কপি করুন। সদস্যটিকে third-party application-এর সঙ্গে যুক্ত কোম্পানির অন্তর্ভুক্ত হতে হবে।

json
{
  "audience": { "type": "USERS", "userIds": ["companyMemberId"] }
}
json
{
  "audience": { "type": "ROLES", "roles": ["roleId"] }
}
  • audience বাদ দিলে বা null পাঠালে যুক্ত কোম্পানির সব eligible active user লক্ষ্য হয়।
  • সংশ্লিষ্ট তালিকায় 1-100টি raw string থাকে; ID trim হয়, ফাঁকা বাদ যায় এবং set deduplicate ও sort হয়।
  • অনুপস্থিত, disabled, deleted বা অন্য কোম্পানির ID উপেক্ষিত হয়; বাকি valid target notification পায়।
  • কোনো valid target না থাকলেও recipientCount=0 দিয়ে শেষ হয়; পুরো কোম্পানিতে fallback হয় না।
  • অন্য selector বাদ বা null রাখা যায়। অন্য মিশ্রণ, অজানা type/field, অনুপস্থিত বা খালি তালিকা, non-string item এবং 100টির বেশি item হলে INVALID_REQUEST ফেরে।

সীমা ও idempotency

  • সম্পূর্ণ body সর্বোচ্চ 256 KiB। requestId, title, body যথাক্রমে 128, 100 ও 1000 Unicode অক্ষর।
  • প্রতি App ID-এর সীমা মিনিটে 10 এবং ঘণ্টায় 100 অনুরোধ।
  • একই requestId ও সমতুল্য normalized content আগের ফল ফেরায়। ছবি, field ও tags-এর ক্রম গুরুত্বপূর্ণ; audience set-এর ক্রম ও duplicate নয়।
  • ভিন্ন content হলে IDEMPOTENCY_CONFLICT ফেরে। শেষ status SUCCESS, PARTIAL_SUCCESS অথবা FAILED হতে পারে।

গ্রহণের প্রতিক্রিয়া

বৈধ অনুরোধ HTTP 202 ফেরায়:

json
{
  "requestId": "order-20260819-001",
  "notificationId": "00000000-0000-0000-0000-000000000001",
  "status": "ACCEPTED"
}

ACCEPTED শুধু বোঝায় Engine অনুরোধটি বিতরণের জন্য সংরক্ষণ করেছে; APNs/FCM বা ডিভাইসে প্রদর্শন নিশ্চিত করে না।

Callback ফলাফল

Callback URL থাকলে Engine চূড়ান্ত ফল পাঠায়:

json
{
  "requestId": "order-20260819-001",
  "status": "PARTIAL_SUCCESS",
  "recipientCount": 8,
  "pushAcceptedCount": 1,
  "pushFailedCount": 1
}

recipientCount হলো নোটিফিকেশন সেন্টারের প্রাপক ব্যবহারকারীর সংখ্যা। pushAcceptedCount ও pushFailedCount হলো Push Outbox ব্যাচের সংখ্যা; এগুলো ব্যবহারকারী বা ডিভাইসের সংখ্যা নয় এবং সিস্টেম ব্যানার পৌঁছানোর প্রমাণও নয়।

Callback পরীক্ষা

অ্যাডমিন প্যানেল থেকে প্রতিবার Callback পরীক্ষা করলে একটি স্বতন্ত্র প্রোব ইভেন্ট পাঠানো হয়:

json
{
  "requestId": "callback-test-<unique-id>",
  "status": "SUCCESS",
  "recipientCount": 1,
  "pushAcceptedCount": 1,
  "pushFailedCount": 0,
  "test": true
}

test এর মান true হলে গঠন যাচাই করে 2xx ফেরত দিন, তবে প্রোবটিকে পাঠানো কোনো নোটিফিকেশন অনুরোধের সঙ্গে মেলাবেন না এবং ব্যবসায়িক ডেলিভারি অবস্থা পরিবর্তন করবেন না। গণনাগুলো স্থির পরীক্ষামূলক মান; এগুলো প্রকৃত প্রাপক বা Push Outbox ব্যাচ নয়।

চূড়ান্ত status হলো SUCCESS, PARTIAL_SUCCESS অথবা FAILED। যেকোনো 2xx দিয়ে স্বীকার করুন।

না হলে 1 মিনিট, 5 মিনিট, 30 মিনিট, 2 ঘণ্টা, 6 ঘণ্টা ও 24 ঘণ্টা পরে পুনরায় চেষ্টা হয়। বর্তমানে HMAC স্বাক্ষর নেই: HTTPS বাধ্যতামূলক করুন, পরীক্ষামূলক নয় এমন ফলাফলের requestId মিলিয়ে নিন, প্রবেশ সীমিত রাখুন এবং Callback idempotent ভাবে প্রক্রিয়া করুন।

ত্রুটির তালিকা

HTTPCodeঅর্থ
400INVALID_REQUESTContent-Type, JSON, আকার বা ফিল্ড অবৈধ।
401INVALID_APP_CREDENTIALSApp ID বা App Secret অবৈধ।
403APPLICATION_INACTIVEঅ্যাপ বা কোম্পানি নিষ্ক্রিয়।
409IDEMPOTENCY_CONFLICTrequestId ভিন্ন বিষয়বস্তুতে পুনর্ব্যবহৃত।
429RATE_LIMITEDঅ্যাপের হারসীমা অতিক্রম করেছে।
503NOTIFICATION_UNAVAILABLEসেবা সাময়িকভাবে অনুপলব্ধ।

নিরাপত্তা ও পাঠানোর পরিধি

  • App ID ও App Secret কেবল server-to-server পরিচয়পত্র। browser, mobile app, প্রকাশ্য repository, URL বা client storage-এ রাখবেন না। ফাঁস হলে App Secret রিসেট করুন।
  • private target ID কখনও application logs-এ লেখা হয় না। private selector ও target ID GraphQL, Push, Callback, realtime বা navigation payload-এও যায় না।
  • audience না থাকলে কোম্পানির সব যোগ্য সক্রিয় ব্যবহারকারী অন্তর্ভুক্ত হয়; audience থাকলে শুধু resolve হওয়া valid target। প্রতিটি valid recipient নোটিফিকেশন সেন্টার রেকর্ড পায় এবং recipientCount-এ গণনা হয়।
  • সিস্টেম Push শুধু সক্রিয় PushInstallation এবং অনুমোদিত BUSINESS বিভাগের ডিভাইসে চেষ্টা করা হয়; তবুও প্রতিটি ডিভাইসে সিস্টেম ব্যানার নিশ্চিত নয়।
  • সম্পূর্ণ imageUrls তালিকা শুধু অনুমোদিত notification detail-এ থাকে; তবে native system banner-এ ছবি দেখাতে Engine imageUrls-এর প্রথম URL APNs/FCM-এ পাঠাতে পারে। displayFields ও tags Push বা Callback-এ যায় না এবং non-interactive plain text; এগুলোতে secret, access token, payment data বা sensitive value দেবেন না।
  • title ও body ছবির সাহায্য ছাড়াই সম্পূর্ণ ও বোধগম্য হতে হবে। ছবি ডাউনলোড বা প্রদর্শন ব্যর্থ হলেও accepted, Callback বা Push status পরিবর্তিত হয় না।
  • Mobile client প্রতিটি ছবির জন্য সর্বোচ্চ 5 MiB গ্রহণ করে এবং সম্পূর্ণ ছবি ডাউনলোড কার্যক্রম 10 সেকেন্ড পরে timeout হয়। Client 3xx redirect অনুসরণ করে না, তাই প্রতিটি URL-কে সরাসরি ছবি ফেরত দিতে হবে।
  • Mobile client সরাসরি public CDN থেকে ছবি নামায়। authentication বা Cookie ছাড়া URL ব্যবহার করুন, অন্তত 90 দিন উপলভ্য রাখুন এবং CDN যে ব্যবহারকারীর IP, request time ও User-Agent পাবে তা বিবেচনা করুন।
  • ঐতিহাসিক প্রদর্শন স্থির রাখতে immutable object URL ব্যবহার করুন।