দ্রুত শুরু
Web Admin থেকে লক্ষ্য কোম্পানির সঙ্গে যুক্ত তৃতীয়-পক্ষ অ্যাপ তৈরি করুন। App ID ও App Secret কপি করুন; চূড়ান্ত ফল দরকার হলে ঐচ্ছিক Callback URL দিন।
Engine ঐচ্ছিক audience-এ নির্বাচিত ব্যবহারকারীদের জন্য রেকর্ড তৈরি করে (default-এ কোম্পানির সব যোগ্য ব্যবহারকারী) এবং শুধু যোগ্য নিবন্ধিত ডিভাইসে সিস্টেম Push পাঠানোর চেষ্টা করে।
Endpoint ও প্রমাণীকরণ
API environment:
- Test: https://aim-api-test.proton-system.com
- Production: https://aim-api.proton-system.com
প্রতিটি server-to-server JSON request-এ HTTP Basic Authentication ব্যবহার করে Authorization: Basic Base64(KEY:SECRET) পাঠাতে হবে, যেখানে KEY হলো App ID এবং SECRET হলো App Secret:
Endpoint: POST /openapi/v1/notifications।
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 | হ্যাঁ | string | notification title; trim করার পর ফাঁকা হওয়া যাবে না। |
body | হ্যাঁ | string | notification body; trim করার পর ফাঁকা হওয়া যাবে না। |
imageUrls | না | string[] | detail-এ ক্রমানুসারে দেখানো ছবির URL। |
displayFields | না | object[] | detail-এ ক্রমানুসারে দেখানো অতিরিক্ত text field। |
tags | না | string[] | শুধু detail-এ ক্রমানুসারে দেখানো plain text tag। |
audience | না | object | users বা company roles-এ সীমিত করে; না দিলে পুরো eligible company। |
ছবি: imageUrls
- ছবি না থাকলে field বাদ দিন,
nullবা[]পাঠান; থাকলে 1-9টি URL ক্রমানুসারে পাঠান। - প্রতিটি URL trim হয়, অনন্য হতে হয় এবং username/password ছাড়া সম্পূর্ণ
HTTPSURL হতে হয়। - প্রতিটি URL সর্বোচ্চ 2048 Unicode অক্ষর। একটি অবৈধ URL পুরো অনুরোধ বাতিল করে।
- Engine URL সংরক্ষণ করে, কিন্তু ছবি আনে, যাচাই করে, proxy বা cache করে না।
Detail field: displayFields
| Subfield | আবশ্যক | সীমা | প্রদর্শন |
|---|---|---|---|
label | না | trim-এর পরে খালি নয়; সর্বোচ্চ 32 Unicode অক্ষর | field name। |
value | হ্যাঁ | trim-এর পরে খালি নয়; সর্বোচ্চ 256 Unicode অক্ষর | field value। |
{
"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
type | Selector | ID-এর অর্থ |
|---|---|---|
USERS | userIds | কোম্পানি সদস্য ID |
ROLES | roles | CompanyRole ID; যেকোনো role-এর eligible member পায়। |
Web Admin-এর কোম্পানি সদস্য তালিকা থেকে কোম্পানি সদস্য ID কপি করুন। সদস্যটিকে third-party application-এর সঙ্গে যুক্ত কোম্পানির অন্তর্ভুক্ত হতে হবে।
{
"audience": { "type": "USERS", "userIds": ["companyMemberId"] }
}{
"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ফেরে। শেষstatusSUCCESS,PARTIAL_SUCCESSঅথবাFAILEDহতে পারে।
গ্রহণের প্রতিক্রিয়া
বৈধ অনুরোধ HTTP 202 ফেরায়:
{
"requestId": "order-20260819-001",
"notificationId": "00000000-0000-0000-0000-000000000001",
"status": "ACCEPTED"
}ACCEPTED শুধু বোঝায় Engine অনুরোধটি বিতরণের জন্য সংরক্ষণ করেছে; APNs/FCM বা ডিভাইসে প্রদর্শন নিশ্চিত করে না।
Callback ফলাফল
Callback URL থাকলে Engine চূড়ান্ত ফল পাঠায়:
{
"requestId": "order-20260819-001",
"status": "PARTIAL_SUCCESS",
"recipientCount": 8,
"pushAcceptedCount": 1,
"pushFailedCount": 1
}recipientCount হলো নোটিফিকেশন সেন্টারের প্রাপক ব্যবহারকারীর সংখ্যা। pushAcceptedCount ও pushFailedCount হলো Push Outbox ব্যাচের সংখ্যা; এগুলো ব্যবহারকারী বা ডিভাইসের সংখ্যা নয় এবং সিস্টেম ব্যানার পৌঁছানোর প্রমাণও নয়।
Callback পরীক্ষা
অ্যাডমিন প্যানেল থেকে প্রতিবার Callback পরীক্ষা করলে একটি স্বতন্ত্র প্রোব ইভেন্ট পাঠানো হয়:
{
"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 ভাবে প্রক্রিয়া করুন।
ত্রুটির তালিকা
| HTTP | Code | অর্থ |
|---|---|---|
| 400 | INVALID_REQUEST | Content-Type, JSON, আকার বা ফিল্ড অবৈধ। |
| 401 | INVALID_APP_CREDENTIALS | App ID বা App Secret অবৈধ। |
| 403 | APPLICATION_INACTIVE | অ্যাপ বা কোম্পানি নিষ্ক্রিয়। |
| 409 | IDEMPOTENCY_CONFLICT | requestId ভিন্ন বিষয়বস্তুতে পুনর্ব্যবহৃত। |
| 429 | RATE_LIMITED | অ্যাপের হারসীমা অতিক্রম করেছে। |
| 503 | NOTIFICATION_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-এ ছবি দেখাতে EngineimageUrls-এর প্রথম URL APNs/FCM-এ পাঠাতে পারে।displayFieldsওtagsPush বা 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 ব্যবহার করুন।