Sindh IT Portal — Facilitation DeskSpecification documents
Englishاردوسنڌي
← All documents

API معاہدہ

سندھ آئی ٹی پورٹل — سہولت ڈیسک (SITP) کے مستند REST API معاہدے کی دستاویز: بیس URL، ورژننگ، تصدیق و اجازت، ریٹ لمٹنگ، پیجینیشن، لفافہ، نقائص، idempotency، OpenAPI 3.1 خاکہ، مکمل وسائل کی فہرست، باہر نکالنے والے ویب ہوک کا معاہدہ، SDK/codegen منصوبہ، deprecation، سینڈ باکس، اور مشاہدہ پذیری۔

فیلڈ قدر
دستاویز آئی ڈی 12
حیثیت مسودہ
مالک S&ITD / MAAHIR
زبانیں EN (مرجع) · UR · SD
API انداز REST (NestJS)، JSON، OpenAPI 3.1
بیس URL https://sindhitportal.maahir.io/api/v1
متعلقہ دستاویزات /specs/ur/08-integrations-spec/ · /specs/ur/05-data-model/ · /specs/ur/04-roles-permissions/ · /specs/ur/11-security-compliance/ · 03-non-functional-requirements/en.md · /specs/ur/15-tech-architecture/

1. دائرہ کار اور اس دستاویز کو پڑھنے کا طریقہ

یہ دستاویز SITP کے عوامی REST API کا انجینئرنگ معاہدہ ہے۔ اسے درج ذیل استعمال کرتے ہیں:

یہ دستاویز API کے خدوخال کے لیے مستند ماخذ ہے۔ یہ /specs/ur/08-integrations-spec/ کے §8 (عوامی API) کو ایک مکمل معاہدے میں توسیع دیتی ہے۔ انضمام کی تفصیلی دستاویز انفرادی انضمام ایڈاپٹرز (NADRA، SECP، Mailjet وغیرہ) کے لیے مستند ماخذ برقرار رہتی ہے؛ یہ دستاویز صرف اس سطح کا احاطہ کرتی ہے جو SITP خود بے نقاب کرتا ہے۔ جہاں دونوں کسی عوامی-API تفصیل پر متفق نہ ہوں، یہ دستاویز حاوی ہے۔

ہر وسیلہ کے پیچھے ڈیٹا ماڈل /specs/ur/05-data-model/ میں متعین ہے؛ API فیلڈ کے نام وہاں دستاویز کردہ snake_case کالموں کے camelCase منعکس ہیں۔


2. بیس URL، ورژننگ اور میڈیا اقسام

2.1 بیس URL

ماحول بیس URL
پروڈکشن https://sindhitportal.maahir.io/api/v1
سینڈ باکس https://sandbox.sindhitportal.maahir.io/api/v1 (دیکھیں §15)
OpenAPI دستاویز GET /api/v1/openapi.json
انٹرایکٹو دستاویزات (Swagger UI) https://sindhitportal.maahir.io/docs/api

اس دستاویز کے تمام پاتھ مکمل طور پر لکھے جانے کے بغیر بیس URL کے نسبت سے ہیں۔

2.2 ورژننگ کی حکمت عملی

SITP URL سیگمنٹ میجر ورژننگ (/api/v1، /api/v2) استعمال کرتا ہے۔ قواعد:

یہ کہ توڑنے والی کیا ہے §14.2 میں دستاویز ہے اور /api/v1/openapi.json پر پیش کردہ چینج لاگ میں ظاہر ہے (OpenAPI کا info.version ایک میجر کے اندر SemVer پر کاربند ہے)۔

2.3 میڈیا اقسام

پہلو قاعدہ
درخواست باڈی Content-Type: application/json (UTF-8)۔ Multipart صرف براہ راست فائل اپ لوڈ کے لیے استعمال ہوتا ہے جب کوئی پارٹنر presigned-URL فلو استعمال نہیں کر سکتا (دیکھیں §10 Attachments)، SITP کے زیرِ ملکیت endپوائنٹ پر۔
جواب باڈی تمام وسائل کے لیے application/json۔ نقائص application/problem+json ہیں (§7)۔
لوکیل Accept-Language: en | ur | sd انسان کے پڑھنے کے قابل فیلڈز (title، displayName، message) کی زبان کنٹرول کرتا ہے۔ نامعلوم قدریں en پر واپس آتی ہیں۔
کیلنڈر Prefer: calendar=hijri تاریخ رکھنے والے فیلڈز میں دوہری گریگورین+ہجری تاریخیں لوٹاتا ہے (_context.md §2 کے مطابق)۔
کمپریشن gzip اور br Accept-Encoding کے ذریعے معاون ہیں۔

2.4 عام ہیڈرز (ہر درخواست)

ہیڈر ضروری مقصد
Authorization ہاں (عوامی + ٹوکن ایکسچینج endپوائنٹس کے سوا) Bearer <access_token> — OAuth2 یا OIDC (§3)۔
Accept-Language نہیں (ڈیفالٹ en) انسان کے پڑھنے کے قابل فیلڈز کی لوکیل۔
X-Request-Id نہیں کلائنٹ کی فراہم کردہ corelation آئی ڈی؛ جواب میں لوٹائی جاتی ہے (§16)۔ اگر غیر حاضر ہو تو SITP ایک تیار کرتا ہے۔
Idempotency-Key تحریروں پر لازم (§8) UUID v4/v7؛ 24 گھنٹوں کے اندر duplicate ہٹاتا ہے۔
User-Agent تجویز کردہ تشخیص کے لیے پارٹنر شناخت کنندہ۔

3. تصدیق و اجازت

SITP دو تصدیقی انداز بے نقاب کرتا ہے، دونوں خود میزبان Keycloak مثال پر ختم ہوتے ہیں (/specs/ur/08-integrations-spec/ §7 کے مطابق):

  1. OAuth 2.0 client-credentialsپارٹنر ایپس کے لیے (مشین سے مشین تک)۔ کوئی آخری صارف عمل میں نہیں۔
  2. OIDC bearer (Authorization Code + PKCE)انٹرایکٹو صارفین کے لیے (کمپنی نمائندے، حکومتی عملہ) جو SITP UI یا کوئی وفاقی حکومتی IdP کے ذریعے لاگ ان ہوتے ہیں۔

دونوں مختصر مدت کے bearer رسائی ٹوکنز (JWTs) پیدا کرتے ہیں جو Authorization: Bearer <token> ہیڈر میں بھیجے جاتے ہیں۔ ٹوکنز کبھی بھی query پیرامیٹرز کے طور پر نہیں بھیجے جاتے۔

3.1 OAuth 2.0 client-credentials (پارٹنر ایپس)

پارٹنر ایپس SITP پارٹنر کنسول میں رجسٹرڈ ہوتی ہیں اور ایک client_id اور client_secret وصول کرتی ہیں۔ ہر پارٹنر ایک یا زیادہ companyId قدروں سے بندھا ہوتا ہے جس کے لیے وہ مجاز ہے (کمپنی پارٹنر کو پورٹل میں OAuth انداز کی رضامندی سے اجازت دیتی ہے)۔ فلو:

ٹوکن درخواست

POST /api/v1/partners/tokens
Content-Type: application/json

{
  "grant_type": "client_credentials",
  "client_id": "partner_acmeintegrator",
  "client_secret": "••••••••••••••••",
  "scope": "tickets:write tickets:read kb:read"
}

ٹوکن جواب

HTTP/1.1 200 OK
Content-Type: application/json
Cache-Control: no-store
Pragma: no-cache

{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "scope": "tickets:write tickets:read kb:read",
  "issued_token_type": "urn:ietf:params:oauth:token-type:access_token"
}

ٹوکن منسوخی

POST /api/v1/partners/tokens/revoke
Authorization: Bearer <partner admin token>
Content-Type: application/json

{ "token": "eyJhbGciOi...", "token_type_hint": "access_token" }

یہ 204 No Content لوٹاتا ہے۔ ایک denylist کو Redis میں عکس بند کیا جاتا ہے تاکہ منسوخی چند سیکنڈوں میں اثر انداز ہو۔

3.2 OIDC bearer (انٹرایکٹو صارفین)

کمپنی نمائندے اور حکومتی عملہ SITP UI کے ذریعے تصدیق کرتے ہیں، جو Keycloak کے خلاف PKCE کے ساتھ OIDC Authorization Code فلو انجام دیتا ہے۔ نتیجے کا رسائی ٹوکن ایک bearer کے طور پر API کو بالکل پارٹنر ٹوکن کی طرح بھیجا جاتا ہے۔ Claims میں sub، email، realm (gov-staff | companyroles[]، deptCode، اور 2fa_verified شامل ہیں (/specs/ur/08-integrations-spec/ §7 کے مطابق)۔ حکومتی عملہ کے ٹوکنز additionally ایک SITP کردار (Staff، POC، DG، Secretary، SuperAdmin) رکھتے ہیں جو RolesGuard/PermissionsGuard استعمال کرتا ہے۔

SITP کے اپنے فرنٹ اینڈ کے لیے، یہ شفاف ہے — SPA ٹوکن کو محفوظ سیشن میں رکھتا ہے۔ تیسرے فریق UI کے لیے جو اسی Keycloak realm سے وفاقی بنتی ہیں، وہی طریقہ کار لاگو ہوتا ہے۔

3.3 اسکوپس

اسکوپس پارٹنر ایپس کے لیے اجازت کی اکائی ہیں۔ انٹرایکٹو صارفین کو کردار + صلاحیت کے ذریعے اجازت دی جاتی ہے (/specs/ur/04-roles-permissions/ کے مطابق)، اسکوپ کے ذریعے نہیں؛ ان کا ٹوکن پھر بھی endپوائنٹ کی مطلوبہ صلاحیت کو پورا کرنا چاہیے۔

اسکوپ اجازتیں
tickets:read مجاز کمپنیوں کے ٹکٹس، پیغامات، اور منسلکات پڑھنا۔
tickets:write ٹکٹ بنانا، پیغامات شامل کرنا، قبول/بند کرنا، منسلکات اپ لوڈ کرنا۔
orgs:read مجاز کمپنیوں کے تنظیمی + نمائندہ ریکارڈز پڑھنا۔
orgs:write تنظیم رجسٹر کرنا، نمائندگان کو مدعو/اپڈیٹ کرنا۔
reps:write نمائندگان کا انتظام (orgs:write کا ذیلی سیٹ)۔
kb:read شائع کردہ KB مضامین اور SOPs پڑھنا۔
stats:read غیر عوامی تجزیاتی حصے پڑھنا (عوامی stats endپوائنٹ کو کوئی اسکوپ درکار نہیں)۔
files:read presigned URL کے ذریعے منسلکہ مواد ڈاؤن لوڈ کرنا۔
files:write اپ لوڈ شروع کرنا / فائلیں منسلک کرنا۔
webhooks:manage ویب ہوک سبسکرپشنز بنانا، فہرست، حذف، دوبارہ چلانا۔
* سوپر-اسکوپ؛ صرف فرسٹ پارٹی SITP کلائنٹس کے لیے محفوظ ہے۔

ایک endپوائنٹ کا مطلوبہ اسکوپ وسائل کی فہرست (§10) اور OpenAPI کے security بلاک (§9) میں درج ہے۔ اسکوپ کی کمی → SITP-AUTH-004 (§7.3)۔

3.4 عوامی (no-auth) endپوائنٹس

کچھ مختصر صرف پڑھنے کے endپوائنٹس عوامی ہیں — کوئی ٹوکن درکار نہیں — تاکہ شہری اور محقق بغیر رجسٹریشن کے انہیں استعمال کر سکیں:

عوامی endپوائنٹس پھر بھی ریٹ لمٹنگ (§4) کے تابع ہیں ایک سخت تر ڈیفالٹ درجے پر۔


4. ریٹ لمٹنگ

ریٹ لمٹس پلیٹ فارم کو غلط استعمال کرنے والے یا بھاگ جانے والے کلائنٹس سے محفوظ رکھتے ہیں۔ لمٹس فی پارٹنر (client_id/ٹوکن سے شناخت کردہ) تصدیق شدہ کالز کے لیے اور فی ماخذ IP عوامی کالز کے لیے ہیں۔ لمٹس int_ratelimit جدول میں تشکیل کے قابل ہیں (/specs/ur/05-data-model/ §3.10 کے مطابق) اور پارٹنر درجے اور آپریشن کلاس کے لحاظ سے مختلف ہیں۔

4.1 درجہ بندی ماڈل

درجہ پڑھنے کا بجٹ لکھنے کا بجٹ (ٹکٹ بنانا) کون
public 120 درخواست/منٹ فی IP n/a (کوئی تحریر نہیں) عوامی endپوائنٹس کے گمنام کالرز۔
standard 600 درخواست/منٹ 60 درخواست/منٹ رجسٹرڈ پارٹنرز کے لیے ڈیفالٹ۔
premium 3 000 درخواست/منٹ 300 درخواست/منٹ معاہدہ شدہ اعلیٰ حجم پارٹنرز (تجارتی درجہ — TBD، دیکھیں §18)۔
first-party 10 000 درخواست/منٹ 1 000 درخواست/منٹ SITP کا اپنا فرنٹ اینڈ، موبائل، اور اندرونی سروسز۔

لکھنے کی لمٹس ہر آپریشن کلاس کے لیے الگ ہیں (ٹکٹ بنانا، پیغام شامل کرنا، اپ لوڈ) تاکہ پڑھنے کا اچھال لکھنے کی گنجائش ختم نہ کر سکے۔ اچھالنے والے کلائنٹس کو throttle کیا جاتا ہے (HTTP 429)، بغیر پہلے اطلاع کے خاموشی سے کبھی banned نہیں کیا جاتا۔

4.2 ریٹ لمٹ ہیڈرز

ہر جواب — کامیاب جوابات سمیت — یہ ہیڈرز رکھتا ہے تاکہ کلائنٹس خود کو منظم کر سکیں:

ہیڈر معنی
X-RateLimit-Limit موجودہ ونڈو کے لیے بجٹ (مثلاً، 600
X-RateLimit-Remaining موجودہ ونڈو میں باقی درخواستیں۔
X-RateLimit-Reset Unix ٹائم اسٹیمپ جس پر ونڈو ری سیٹ ہوتی ہے۔
X-RateLimit-Tier وہ درجہ جو لاگو ہوا (public/standard/premium/first-party

جب تجاوز کر جائے:

HTTP/1.1 429 Too Many Requests
Content-Type: application/problem+json
Retry-After: 28
X-RateLimit-Limit: 600
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1752752522

{
  "type": "https://sindhitportal.maahir.io/docs/errors/rate-limited",
  "title": "Rate limit exceeded",
  "status": 429,
  "detail": "You have exceeded 600 requests per minute. Retry after the Retry-After window.",
  "instance": "/api/v1/tickets",
  "code": "SITP-RATELIMIT-001",
  "retryAfterSeconds": 28
}

Retry-After ہمیشہ 429 پر موجود ہوتا ہے اور سیکنڈوں میں دیا جاتا ہے۔


5. پیجینیشن، فلٹرنگ، ترتیب دینا اور Sparse Fieldsets

5.1 پیجینیشن (cursor + page)

SITP فہرست endپوائنٹس کے لیے دو پیجینیشن انداز معاون ہے۔ Cursor اعلیٰ حجم، ترتیب دی گئی فہرستوں کے لیے ترجیحی ہے؛ page سہولت اور ایڈمن UIs کے لیے معاون ہے۔

انداز پیرامیٹرز کب استعمال کریں
Cursor (ڈیفالٹ) ?cursor=<opaque>&limit=50 /tickets، /tickets/{id}/messages، /kb/articles کے لیے ڈیفالٹ۔ داخلے/حذف ہونے پر مستحکم؛ زیادہ سے زیادہ limit=100، ڈیفالٹ 50۔
Page ?page=1&pageSize=50 /departments، /service-catalog، /stats/public پر اجازت۔ آسان UIs کے لیے آسان؛ page 1-اشاری شدہ ہے؛ زیادہ سے زیادہ pageSize=100۔

Cursor ٹوکنز کلائنٹ کے لیے opaque ہیں (ایک base64url-encoded signed سٹرنگ)؛ کلائنٹس کو انہیں black box سمجھنا چاہیے اور صرف واپس بھیج دینا چاہیے۔ جواب ہمیشہ links بلاک (§6) کے ذریعے کلائنٹ کو جاری رکھنے کا طریقہ بتاتا ہے۔

5.2 فلٹرنگ

فلٹرز فی endپوائنٹ whitelist-کی گئی تصدیق شدہ query پیرامیٹرز ہیں۔ نامعلوم فلٹرز SITP-VALIDATION-005 کے ساتھ مسترد کیے جاتے ہیں۔ عام فلٹرز:

فلٹر مثال نوٹس
حیثیت ?status=assigned,in_progress کومے سے جدا multi-value؛ اندر OR۔
محکمہ ?dept=SRB محکمہ کوڈ۔
زمرہ ?category=SRB-REFUND زمرہ کوڈ۔
تاریخ کی حد ?since=2026-07-01T00:00:00Z&until=2026-07-31T23:59:59Z ISO-8601، UTC۔
تلاش ?q=refund سرور Meilisearch کو تفویض کرتا ہے؛ کثیر لسانی (/specs/ur/05-data-model/ §2.7 کے مطابق)۔
KB پر full-text ?q=tax&locale=ur KB تلاش لوکیل کا احترام کرتی ہے۔

5.3 ترتیب دینا

?sort=<field> صعودی؛ ?sort=-<field> نزولی (ابتدائی -)۔ multi-sort: ?sort=-createdAt,priority۔ ترتیب دینے کے قابل فیلڈز فی endپوائنٹ OpenAPI میں درج ہیں؛ غیر ترتیب دینے کے قابل فیلڈ سے ترتیب دینے پر SITP-VALIDATION-006 لوٹتا ہے۔

5.4 Sparse fieldsets

کلائنٹس صرف وہ فیلڈز مانگ سکتے ہیں جو انہیں درکار ہیں تاکہ payload سائز کم ہو، جو موبائل اور میٹرڈ نیٹ ورکس کے لیے مفید ہے:

GET /api/v1/tickets/SITP-2026-SRB-000128?fields=ticketId,status,sla
Authorization: Bearer <token>

صرف data کے اندر مانگے گئے اعلیٰ سطحی فیلڈز لوٹاتا ہے۔ نامعلوم یا غیر مجاز فیلڈز خاموشی سے چھوڑ دیے جاتے ہیں (نقص نہیں) تاکہ کلائنٹس forward-compatible رہیں۔ Nested sparse selection dot-paths استعمال کرتا ہے: ?fields=ticketId,sla.responseBy۔


6. جواب کا لفافہ

ہر کامیاب جواب اسی لفافے کا استعمال کرتا ہے: { data, meta, links }۔ واحد وسیلہ جوابات وسیلہ کو data میں رکھتے ہیں اور خالی ہونے پر meta/links کو چھوڑ دیتے ہیں؛ فہرست جوابات تینوں کو بھرتے ہیں۔

فیلڈ ہمیشہ موجود؟ معنی
data ہاں وسیلہ (آبجیکٹ) یا وسائل (array)۔ صرف 204 جوابات کے لیے null۔
meta نہیں Out-of-band میٹا ڈیٹا: requestId، پیجینیشن شمار، ریٹ لمٹ eco، سرور گھڑی، استعمال شدہ لوکیل۔
links نہیں پیجینیشن/نیویگیشن لنکس: self، next، prev، first، last۔

لفافہ مثال (cursor پیجینیشن کے ساتھ فہرست)

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01HZX9F8K7P4N2Q3R6STV8WXAB
X-SITP-API-Version: v1

{
  "data": [
    { "ticketId": "SITP-2026-SRB-000127", "status": "assigned" },
    { "ticketId": "SITP-2026-SRB-000128", "status": "new" }
  ],
  "meta": {
    "requestId": "req_01HZX9F8K7P4N2Q3R6STV8WXAB",
    "locale": "en",
    "serverTime": "2026-07-17T09:18:42.117Z",
    "page": { "limit": 50, "returned": 2, "hasMore": true }
  },
  "links": {
    "self":  "/api/v1/tickets?cursor=eyJpZCI6MTI3fQ&limit=50",
    "next":  "/api/v1/tickets?cursor=eyJpZCI6MTIyOH0&limit=50",
    "prev":  null,
    "first": "/api/v1/tickets?limit=50"
  }
}

لفافہ مثال (واحد وسیلہ)

{
  "data": {
    "ticketId": "SITP-2026-SRB-000128",
    "status": "new"
  },
  "meta": { "requestId": "req_01HZX9F8K7P4N2Q3R6STV8WXAB" }
}

نقائص اس لفافے کا استعمال نہیں کرتے — وہ RFC 7807 (§7) استعمال کرتے ہیں۔


7. نقائص (RFC 7807 Problem Details)

تمام نقائص RFC 7807 (application/problem+json) استعمال کرتے ہیں۔ ہر نقص معیاری فیلڈز کے علاوہ ایک SITP مخصوص code (مستحکم، مشین کے پڑھنے کے قابل) رکھتا ہے۔ کلائنٹس کو code پر branch کرنا چاہیے، کبھی detail پر نہیں (جو انسان کے پڑھنے کے قابل اور localized ہے)۔

7.1 معیاری فیلڈز

فیلڈ قسم معنی
type URI نقص کی زمرہ بندی کے لیے ایک دستاویزی صفحہ (dereferenceable)۔
title سٹرنگ مختصر، مستحکم، انگریزی خلاصہ۔
status int HTTP اسٹیٹس (echoed)۔
detail سٹرنگ انسان کے پڑھنے کے قابل وضاحت، Accept-Language کے ذریعے localized۔
instance URI وہ درخواست پاتھ جو ناکام ہوا۔
code سٹرنگ SITP نقص کوڈ، مثلاً، SITP-VALIDATION-042۔
errors[] array (صرف validation) فی فیلڈ تفصیل field اور code کے ساتھ۔
requestId سٹرنگ corelation آئی ڈی (§16)، ہمیشہ موجود۔

7.2 Validation نقص کی مثال

HTTP/1.1 422 Unprocessable Entity
Content-Type: application/problem+json
X-Request-Id: req_01HZX9F8K7P4N2Q3R6STV8WXAC

{
  "type": "https://sindhitportal.maahir.io/docs/errors/validation",
  "title": "Validation failed",
  "status": 422,
  "detail": "companyId does not match the partner's authorized scope.",
  "instance": "/api/v1/tickets",
  "code": "SITP-VALIDATION-042",
  "requestId": "req_01HZX9F8K7P4N2Q3R6STV8WXAC",
  "errors": [
    { "field": "companyId", "code": "SCOPE_MISMATCH" },
    { "field": "attachments[0].size", "code": "MAX_SIZE_EXCEEDED" }
  ]
}

7.3 نقص کوڈ کی فہرست

اسٹیٹس کوڈز HTTP پر کاربند ہیں۔ SITP نقص کوڈز خاندان کے لحاظ سے گروہ بند ہیں۔ یہ فہرست https://sindhitportal.maahir.io/docs/errors پر live پیش کی جاتی ہے اور OpenAPI دستاویز میں versioned ہے۔

code HTTP خاندان معنی
SITP-AUTH-001 401 Auth Authorization ہیڈر غیر موجود۔
SITP-AUTH-002 401 Auth ٹوکن ختم یا malformed۔
SITP-AUTH-003 400 Auth مطلوبہ اسکوپ کلائنٹ کو دیا نہیں۔
SITP-AUTH-004 403 Auth ٹوکن درست مگر اس endپوائنٹ کے لیے مطلوبہ اسکوپ غیر موجود۔
SITP-AUTH-005 403 Auth اس عمل کے لیے 2FA لازم (حساس/VIP)۔
SITP-AUTH-006 403 Auth کمپنی نمائندہ certified نہیں (Module O گیٹ)۔
SITP-RATELIMIT-001 429 Rate limit ریٹ لمٹ تجاوز (دیکھیں §4)۔
SITP-VALIDATION-001 400 Validation Malformed JSON باڈی۔
SITP-VALIDATION-002 400 Validation لازم فیلڈ غیر موجود۔
SITP-VALIDATION-003 400 Validation غلط فیلڈ قدر (format/range)۔
SITP-VALIDATION-004 422 Validation کاروباری اصول کی خلاف ورزی (مثلاً، proof گیٹ پورا نہیں)۔
SITP-VALIDATION-005 400 Validation نامعلوم فلٹر پیرامیٹر۔
SITP-VALIDATION-006 400 Validation غیر ترتیب دینے کے قابل فیلڈ۔
SITP-VALIDATION-042 422 Validation companyId پر اسکوپ عدمِ مطابقت۔
SITP-NOTFOUND-001 404 Not found وسیلہ موجود نہیں۔
SITP-NOTFOUND-002 404 Not found وسیلہ موجود مگر کالر کی visibility نہیں (001 جیسا خدوخال تاکہ موجودگی leak نہ ہو)۔
SITP-CONFLICT-001 409 Conflict موجودہ حیثیت سے اسٹیٹ ٹرانزیشن کی اجازت نہیں۔
SITP-CONFLICT-002 409 Conflict idempotency کلید duplicate مگر مختلف payload۔
SITP-CONFLICT-003 409 Conflict ٹکٹ پہلے ضم/بند ہو چکا۔
SITP-UPLOAD-001 413 Upload منسلکہ فی فائل سائز لمٹ سے تجاوز۔
SITP-UPLOAD-002 415 Upload غیر معاون MIME قسم۔
SITP-UPLOAD-003 422 Upload AV سکین نے فائل کو متاثر قرار دیا۔
SITP-DEPENDENCY-001 502 Dependency اوپرStream انضمام (NADRA/SECP/…) دستیاب نہیں؛ بعد میں دوبارہ کوشش۔
SITP-DEPENDENCY-002 503 Dependency ایک مطلوبہ ایڈاپٹر کے لیے سرکٹ بریکر کھلا ہوا۔
SITP-INTERNAL-001 500 Internal Unhandled سرور نقص؛ corelation آئی ڈی requestId میں۔

4xx نقائص (429 کے سوا) کلائنٹس کے ذریعے کبھی دوبارہ کوشش نہیں کیے جاتے۔ 5xx اور 429 کو exponential backoff کے ساتھ دوبارہ کوشش کیا جا سکتا ہے (دیکھیں §8 اور /specs/ur/08-integrations-spec/ §11.2)۔


8. Idempotency

ہر تحریر (POST، PUT، PATCH، DELETE جو state بدلے) Idempotency-Key ہیڈر قبول کرتی ہے۔ ہیڈر کلائنٹ کا پیدا کردہ UUID v4 یا v7 ہے۔ 24 گھنٹے کی idempotency ونڈو کے اندر (/specs/ur/08-integrations-spec/ §11 میں NFR-INT-004 کے مطابق):

تحریر پر Idempotency-Key کی کمی SITP-VALIDATION-001 لوٹاتی ہے جس میں ہیڈر کی طرف اشارہ ہوتا ہے۔ یہ ہیڈر audit_logs.request_id correlation میں بھی ظاہر ہوتا ہے (/specs/ur/05-data-model/ §3.10 کے مطابق) تاکہ ایک تحریر اور اس کے نتیجے میں ہونے والے انضمام کالز ایک thread میں شریک ہوں۔

POST /api/v1/tickets
Authorization: Bearer <token>
Idempotency-Key: 9a2c4e6b-1f3d-4a2c-9e8b-7d6c5b4a3f2e
Content-Type: application/json

{ "companyId": "cmp_01HZX7K4P9N2Q3R6STV8WXYPJ", "title": "..." }

24 گھنٹوں کے اندر مماثل درخواست دہرانا اصل 201 Created اسی ticketId کے ساتھ لوٹاتا ہے، نہ کہ duplicate ٹکٹ۔


9. OpenAPI 3.1 خاکہ

مکمل OpenAPI 3.1 دستاویز NestJS کنٹرولرز سے @nestjs/swagger کے ذریعے پیدا کی جاتی ہے اور /api/v1/openapi.json پر پیش کی جاتی ہے، پھر /docs/api پر render ہوتی ہے۔ نیچے دیا گیا خاکہ اعلیٰ سطحی دستاویزی خدوخال اور تین نمائندگی کرنے والے آپریشنز (POST /partners/tokens، POST /tickets، GET /tickets/{ticketId}) دکھاتا ہے۔ یہ مثالی ہے، مکمل نہیں۔

openapi: 3.1.0
info:
  title: Sindh IT Portal — Facilitation Desk Public API
  version: 1.4.0
  description: >
    REST API for partner apps and interactive clients of the Sindh IT Portal.
    Base URL: https://sindhitportal.maahir.io/api/v1
  contact:
    name: SITP API Support
    email: api-support@sindhitportal.maahir.io
  license:
    name: Proprietary — Government of Sindh
servers:
  - url: https://sindhitportal.maahir.io/api/v1
    description: Production
  - url: https://sandbox.sindhitportal.maahir.io/api/v1
    description: Sandbox
tags:
  - name: Auth
  - name: Tickets
  - name: TicketMessages
  - name: Attachments
  - name: Organizations
  - name: Representatives
  - name: Departments
  - name: ServiceCatalog
  - name: KnowledgeBase
  - name: PublicStats
  - name: Webhooks
security:
  - bearerAuth: []
  - oauth2: [tickets:read]
paths:
  /partners/tokens:
    post:
      tags: [Auth]
      summary: Exchange client credentials for a bearer token (OAuth2 client-credentials)
      operationId: createPartnerToken
      security: []            # public endpoint
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/TokenRequest' }
      responses:
        '200':
          description: Token issued
          content:
            application/json:
              schema: { $ref: '#/components/schemas/TokenResponse' }
        '400': { $ref: '#/components/responses/Problem' }
        '401': { $ref: '#/components/responses/Problem' }
  /tickets:
    post:
      tags: [Tickets]
      summary: Create a ticket on behalf of a company
      operationId: createTicket
      security:
        - bearerAuth: []
        - oauth2: [tickets:write]
      parameters:
        - $ref: '#/components/parameters/IdempotencyKey'
        - $ref: '#/components/parameters/AcceptLanguage'
      requestBody:
        required: true
        content:
          application/json:
            schema: { $ref: '#/components/schemas/TicketCreateRequest' }
      responses:
        '201':
          description: Ticket created
          headers:
            Location: { schema: { type: string } }
          content:
            application/json:
              schema: { $ref: '#/components/schemas/TicketEnvelope' }
        '400': { $ref: '#/components/responses/Problem' }
        '401': { $ref: '#/components/responses/Problem' }
        '403': { $ref: '#/components/responses/Problem' }
        '422': { $ref: '#/components/responses/Problem' }
        '429': { $ref: '#/components/responses/Problem' }
    get:
      tags: [Tickets]
      summary: List tickets for the authorized company (cursor pagination)
      operationId: listTickets
      security:
        - bearerAuth: []
        - oauth2: [tickets:read]
      parameters:
        - in: query
          name: cursor
          schema: { type: string }
        - in: query
          name: limit
          schema: { type: integer, minimum: 1, maximum: 100, default: 50 }
        - in: query
          name: status
          schema: { type: array, items: { type: string } }
        - in: query
          name: dept
          schema: { type: string }
        - in: query
          name: since
          schema: { type: string, format: date-time }
      responses:
        '200':
          description: A page of tickets
          content:
            application/json:
              schema: { $ref: '#/components/schemas/TicketListEnvelope' }
        '401': { $ref: '#/components/responses/Problem' }
        '429': { $ref: '#/components/responses/Problem' }
  /tickets/{ticketId}:
    get:
      tags: [Tickets]
      summary: Get a single ticket by tracking id
      operationId: getTicket
      security:
        - bearerAuth: []
        - oauth2: [tickets:read]
      parameters:
        - in: path
          name: ticketId
          required: true
          schema: { type: string, example: SITP-2026-SRB-000128 }
        - in: query
          name: fields
          description: Sparse fieldset
          schema: { type: string, example: ticketId,status,sla }
      responses:
        '200':
          description: The ticket
          content:
            application/json:
              schema: { $ref: '#/components/schemas/TicketEnvelope' }
        '404': { $ref: '#/components/responses/Problem' }
components:
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      bearerFormat: JWT
    oauth2:
      type: oauth2
      flows:
        clientCredentials:
          tokenUrl: /api/v1/partners/tokens
          scopes:
            tickets:read:  Read tickets, messages, attachments
            tickets:write: Create and mutate tickets
            orgs:read:     Read organization records
            orgs:write:    Register and manage organizations
            reps:write:    Manage representatives
            kb:read:       Read published KB articles
            stats:read:    Read non-public analytics slices
            files:read:    Download attachments
            files:write:   Upload and attach files
            webhooks:manage: Manage webhook subscriptions
  parameters:
    IdempotencyKey:
      in: header
      name: Idempotency-Key
      required: true
      schema: { type: string, format: uuid }
    AcceptLanguage:
      in: header
      name: Accept-Language
      required: false
      schema: { type: string, enum: [en, ur, sd], default: en }
  responses:
    Problem:
      description: An RFC 7807 problem document
      content:
        application/problem+json:
          schema: { $ref: '#/components/schemas/Problem' }
  schemas:
    Problem:
      type: object
      required: [type, title, status, code]
      properties:
        type:     { type: string, format: uri }
        title:    { type: string }
        status:   { type: integer }
        detail:   { type: string }
        instance: { type: string }
        code:     { type: string, example: SITP-VALIDATION-042 }
        requestId:{ type: string }
        errors:
          type: array
          items:
            type: object
            properties:
              field: { type: string }
              code:  { type: string }

مکمل دستاویز §10 کے ہر آپریشن کے لیے یہی پیٹرن دہراتی ہے، بشمول request-body schemas، response envelopes، ہر دستاویزی status کے لیے problem-details، اور §12 کے واقعات کے لیے webhooks: ایکسٹینشن (OpenAPI 3.1 native webhooks کی معاونت رکھتا ہے)۔


10. وسائل کی فہرست

نیچے دی گئی فہرست v1 کا ہر endپوائنٹ درج کرتی ہے۔ فیلڈ نام مستحکم ہیں؛ مکمل schemas /api/v1/openapi.json میں ہیں۔ ہر قطار رکھتی ہے: HTTP میتھڈ، پاتھ، مقصد، مطلوبہ auth اسکوپ (یا public)، اور آیا تحریر idempotent ہے (Idempotency-Key قبول کرتی ہے)۔

ضابطے: GET/HEAD کبھی idempotent-keyed نہیں۔ {ticketId} صارف کا سامنے کا ٹریکنگ آئی ڈی SITP-YYYY-DEPT-NNNNNN ہے۔ تمام {orgId}/{repId} opaque SITP ids ہیں۔

10.1 Auth

میتھڈ پاتھ مقصد اسکوپ Idempotent؟
POST /partners/tokens client credentials کا bearer ٹوکن سے تبادلہ۔ — (public) ہاں
POST /partners/tokens/revoke ٹوکن منسوخ کرنا۔ * (partner admin) ہاں

10.2 Tickets

میتھڈ پاتھ مقصد اسکوپ Idempotent؟
POST /tickets کسی کمپنی کی طرف سے ٹکٹ بنانا۔ tickets:write ہاں
GET /tickets مجاز کمپنی کے ٹکٹس کی فہرست۔ tickets:read نہیں
GET /tickets/{ticketId} حیثیت، SLA، تاریخ کے ساتھ ایک ٹکٹ حاصل کریں۔ tickets:read نہیں
PATCH /tickets/{ticketId} قابلِ ترمیم ٹکٹ فیلڈز (ترجیح، زمرہ) اپڈیٹ کریں۔ tickets:write ہاں
POST /tickets/{ticketId}/accept کمپنی حل قبول کرتی ہے → آٹو کلوز ٹرگر۔ tickets:write ہاں

10.3 TicketMessages

میتھڈ پاتھ مقصد اسکوپ Idempotent؟
GET /tickets/{ticketId}/messages عوامی-thread پیغامات کی فہرست۔ tickets:read نہیں
POST /tickets/{ticketId}/messages ایک عوامی پیغام شامل کرنا۔ tickets:write ہاں

10.4 Attachments

میتھڈ پاتھ مقصد اسکوپ Idempotent؟
POST /uploads اپ لوڈ شروع کرنا؛ presigned URL + uploadId لوٹاتا ہے۔ files:write ہاں
GET /tickets/{ticketId}/attachments ٹکٹ پر منسلکات کی فہرست۔ tickets:read نہیں
GET /attachments/{attachmentId} منسلکہ میٹا ڈیٹا + مختصر مدت کا ڈاؤن لوڈ URL حاصل کریں۔ files:read نہیں

تجویز کردہ پارٹنر فلو MinIO تک presigned-URL اپ لوڈ ہے (پارٹنر bytes براہ راست آبجیکٹ اسٹوریج کو PUT کرتا ہے؛ SITP bytes کبھی proxy نہیں کرتا)۔ PUT مکمل ہونے کے بعد، پارٹنر uploadId کو POST /tickets میں refer کرتا ہے (/specs/ur/08-integrations-spec/ کے §11.3 کو دیکھیں)۔ ہر اپ لوڈ قابلِ اتصال ہونے سے پہلے ClamAV کے ذریعے AV-scan ہوتا ہے (متاثر ہو تو SITP-UPLOAD-003/specs/ur/05-data-model/ §4.4 media_library.av_status کے مطابق)۔

10.5 Organizations

میتھڈ پاتھ مقصد اسکوپ Idempotent؟
POST /organizations نئی تنظیم رجسٹر کرنا (file-first → عارضی)۔ orgs:write ہاں
GET /organizations/{orgId} تنظیم ریکارڈ + تصدیقی حیثیت حاصل کریں۔ orgs:read نہیں
GET /organizations/me کالر کی اپنی تنظیم حاصل کریں (ٹوکن سے)۔ orgs:read نہیں

10.6 Representatives

میتھڈ پاتھ مقصد اسکوپ Idempotent؟
GET /organizations/{orgId}/representatives نمائندگان کی فہرست۔ orgs:read نہیں
POST /organizations/{orgId}/representatives ایک نمائندہ مدعو کرنا۔ reps:write ہاں
PATCH /representatives/{repId} نمائندہ اپڈیٹ کرنا (کردار، رابطہ، حیثیت)۔ reps:write ہاں

10.7 Departments

میتھڈ پاتھ مقصد اسکوپ Idempotent؟
GET /departments محکموں کی فہرست (شجرہ)۔ public نہیں
GET /departments/{deptId} شعبوں، اوقات، چھٹیوں کے ساتھ ایک محکمہ حاصل کریں۔ public نہیں

10.8 ServiceCatalog

میتھڈ پاتھ مقصد اسکوپ Idempotent؟
GET /service-catalog زمرہ جات اور SLAs کے ساتھ پیش کردہ سروسز کی فہرست۔ public نہیں
GET /service-catalog/{serviceId} لازم فیلڈز اور ڈیفالٹ SLA کے ساتھ ایک سروس حاصل کریں۔ public نہیں

10.9 KnowledgeBase

میتھڈ پاتھ مقصد اسکوپ Idempotent؟
GET /kb/articles شائع شدہ KB مضامین کی فہرست/تلاش (کثیر لسانی)۔ public (subset) / kb:read (full) نہیں
GET /kb/articles/{articleId} مطلوبہ لوکیل میں ایک KB مضمون حاصل کریں۔ public / kb:read نہیں

10.10 PublicStats

میتھڈ پاتھ مقصد اسکوپ Idempotent؟
GET /stats/public عوامی شفافیت ڈیش بورڈ مجموعات (gumnami شدہ)۔ public نہیں
GET /stats/public/summary سرخی KPIs (کل، محکمے کے لحاظ سے، حیثیت کے لحاظ سے)۔ public نہیں

عوامی-stats payloads /specs/ur/17-analytics-kpis/ میں تجزیاتی ماڈل سے اخذ کردہ gumnami شدہ مجموعات ہیں۔ کوئی انفرادی ٹکٹ یا کمپنی شناخت کے قابل نہیں۔

10.11 Webhooks

میتھڈ پاتھ مقصد اسکوپ Idempotent؟
GET /webhooks/subscriptions کالر کی ویب ہوک سبسکرپشنز کی فہرست۔ webhooks:manage نہیں
POST /webhooks/subscriptions ایک ویب ہوک سبسکرپشن بنانا (URL + events + secret)۔ webhooks:manage ہاں
DELETE /webhooks/subscriptions/{subId} ایک سبسکرپشن حذف کرنا۔ webhooks:manage ہاں
POST /webhooks/subscriptions/{subId}/replay ماضی کے واقعات کی ایک ونڈو دوبارہ چلانا۔ webhooks:manage ہاں

کل v1 endپوائنٹس: 30۔


11. نمونہ درخواست/جواب Flows

تین end-to-end flows جو لفافہ، idempotency، نقائص، اور پیجینیشن کو استعمال کرتے ہیں۔ فیلڈ نام /specs/ur/05-data-model/ کا عکس ہیں (API کے لیے camelCased)۔

11.1 ٹکٹ بنانا (پارٹنر، کسی کمپنی کی طرف سے)

ایک پارٹنر ایپ مجاز کمپنی کی طرف سے ٹکٹ درج کرتی ہے، پہلے اپ لوڈ کردہ فائل منسلک کرتی ہے۔ کال idempotent ہے؛ اسی Idempotency-Key کو 24 گھنٹوں کے اندر دہرانا مماثل 201 جواب لوٹاتا ہے (کوئی duplicate ٹکٹ نہیں)۔

درخواست

POST /api/v1/tickets
Host: sindhitportal.maahir.io
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIs...
Idempotency-Key: 9a2c4e6b-1f3d-4a2c-9e8b-7d6c5b4a3f2e
X-Request-Id: req_01HZX9F8K7P4N2Q3R6STV8WXAB
Accept-Language: en
Content-Type: application/json

{
  "companyId": "cmp_01HZX7K4P9N2Q3R6STV8WXYPJ",
  "title": "Pending sales tax refund for Q4 2025",
  "description": "Our company filed the Q4 2025 SRB refund on 15 Jan 2026; no acknowledgment received.",
  "category": "SRB-REFUND",
  "targetDept": "SRB",
  "priority": "normal",
  "language": "en",
  "attachments": [
    {
      "filename": "SRB-Q4-2025-filing.pdf",
      "mimeType": "application/pdf",
      "size": 482310,
      "uploadId": "fil_upl_01HZX9F8K7P4N2Q3R6STV8WXY"
    }
  ],
  "requestedBy": { "repId": "rep_01HZX7K4P9N2Q3R6STV8WXYPJ" }
}

جواب

HTTP/1.1 201 Created
Content-Type: application/json
Location: /api/v1/tickets/SITP-2026-SRB-000128
X-Request-Id: req_01HZX9F8K7P4N2Q3R6STV8WXAB
X-SITP-API-Version: v1
X-RateLimit-Tier: standard
X-RateLimit-Remaining: 599

{
  "data": {
    "ticketId": "SITP-2026-SRB-000128",
    "status": "new",
    "state": "triage-pending",
    "category": "SRB-REFUND",
    "targetDept": "SRB",
    "priority": "normal",
    "sla": {
      "responseBy": "2026-07-19T09:00:00Z",
      "resolveBy": "2026-07-27T09:00:00Z",
      "paused": false
    },
    "createdAt": "2026-07-17T09:18:42.117Z",
    "portalUrl": "https://sindhitportal.maahir.io/tickets/SITP-2026-SRB-000128",
    "attachments": [
      {
        "filename": "SRB-Q4-2025-filing.pdf",
        "attachmentId": "fil_att_01HZX9F8K7P4N2Q3R6STV8WXZ",
        "size": 482310,
        "isEvidence": false
      }
    ]
  },
  "meta": {
    "requestId": "req_01HZX9F8K7P4N2Q3R6STV8WXAB",
    "locale": "en",
    "serverTime": "2026-07-17T09:18:42.117Z"
  }
}

اسی Idempotency-Key اور مماثل باڈی کے ساتھ duplicate POST اسی 201 (اسی ticketId کے ساتھ) لوٹاتا ہے، 409/duplicate کے بجائے؛ اسی کلید کے ساتھ مختلف باڈی 409 SITP-CONFLICT-002 لوٹاتی ہے (§8)۔

11.2 ٹکٹ حیثیت حاصل کرنا (پڑھنا، sparse fieldset)

ایک پارٹنر ایک ٹکٹ poll کرتا ہے اور صرف حیثیت + SLA فیلڈز مانگتا ہے تاکہ میٹرڈ موبائل لنک پر payload کم سے کم رہے۔ یہ sparse-fieldset query (§5.4) استعمال کرتا ہے۔

درخواست

GET /api/v1/tickets/SITP-2026-SRB-000128?fields=ticketId,status,sla,assignedTo
Host: sindhitportal.maahir.io
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIs...
Accept-Language: en
X-Request-Id: req_01HZX9F8K7P4N2Q3R6STV8WXAE

جواب

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01HZX9F8K7P4N2Q3R6STV8WXAE
X-SITP-API-Version: v1
X-RateLimit-Remaining: 587

{
  "data": {
    "ticketId": "SITP-2026-SRB-000128",
    "status": "assigned",
    "assignedTo": { "dept": "SRB", "section": "Refunds" },
    "sla": {
      "responseBy": "2026-07-19T09:00:00Z",
      "resolveBy": "2026-07-27T09:00:00Z",
      "paused": false,
      "firstResponseAt": null
    }
  },
  "meta": {
    "requestId": "req_01HZX9F8K7P4N2Q3R6STV8WXAE",
    "locale": "en",
    "serverTime": "2026-07-17T10:02:13.004Z",
    "requestedFields": ["ticketId", "status", "sla", "assignedTo"]
  }
}

جن فیلڈز کی درخواست نہیں (title، description، attachments، createdAt، …) انہیں چھوڑ دیا جاتا ہے۔ اگر ٹکٹ موجود نہ ہو یا کالر کی visibility نہ ہو تو جواب 404 SITP-NOTFOUND-001 (§7.3) ہے — دونوں کے لیے ایک ہی خدوخال، تاکہ موجودگی leak نہ ہو۔

11.3 عوامی stats کی فہرست (گمنام، کوئی auth نہیں)

ایک شہری یا محقق gumnami شدہ عوامی-شفافیت مجموعات لاتا ہے۔ کوئی ٹوکن درکار نہیں؛ public ریٹ لمٹ درجے (§4.1) کا تابع۔

درخواست

GET /api/v1/stats/public?since=2026-07-01T00:00:00Z&until=2026-07-31T23:59:59Z&limit=20
Host: sindhitportal.maahir.io
Accept-Language: en
X-Request-Id: req_01HZX9F8K7P4N2Q3R6STV8WXAF

جواب

HTTP/1.1 200 OK
Content-Type: application/json
X-Request-Id: req_01HZX9F8K7P4N2Q3R6STV8WXAF
X-SITP-API-Version: v1
X-RateLimit-Tier: public
X-RateLimit-Remaining: 118

{
  "data": {
    "window": { "since": "2026-07-01T00:00:00Z", "until": "2026-07-31T23:59:59Z" },
    "totals": {
      "ticketsReceived": 4821,
      "ticketsResolved": 3104,
      "ticketsClosed": 2877,
      "avgResolutionHours": 53.2,
      "medianResolutionHours": 38.0,
      "csatAverage": 4.2,
      "withinSlaPercent": 87.4
    },
    "byDepartment": [
      { "dept": "SRB",  "received": 1210, "resolved": 902, "withinSlaPercent": 91.1 },
      { "dept": "SITD", "received": 988,  "resolved": 741, "withinSlaPercent": 89.0 },
      { "dept": "LBR",  "received": 612,  "resolved": 388, "withinSlaPercent": 81.3 },
      { "dept": "FIN",  "received": 457,  "resolved": 290, "withinSlaPercent": 84.6 }
    ],
    "byStatus": {
      "new": 612, "triaged": 233, "assigned": 410,
      "in_progress": 374, "resolved": 227, "closed": 2877, "reopened": 88
    },
    "generatedAt": "2026-07-17T10:05:00.000Z"
  },
  "meta": {
    "requestId": "req_01HZX9F8K7P4N2Q3R6STV8WXAF",
    "locale": "en",
    "serverTime": "2026-07-17T10:05:11.882Z",
    "anonymized": true,
    "page": { "limit": 20, "returned": 4, "hasMore": false }
  },
  "links": {
    "self": "/api/v1/stats/public?since=2026-07-01T00:00:00Z&until=2026-07-31T23:59:59Z&limit=20"
  }
}

byDepartment اور byStatus تفصیلات nightly pre-aggregate ہوتی ہیں (/specs/ur/17-analytics-kpis/ کے مطابق) اور cache ہوتی ہیں؛ meta.anonymized: true flag عوامی-stats جوابات پر ہمیشہ موجود ہوتا ہے۔ کسی بھی عوامی-stats payload میں کوئی انفرادی ٹکٹ، کمپنی، یا نمائندہ شناخت کے قابل نہیں۔


12. ویب ہوک معاہدہ

ویب ہوکس پارٹنر ایپس کو polling کے بغیر real time میں SITP واقعات پر ردعمل ظاہر کرنے کی سہولت دیتے ہیں۔ یہ سیکشن پارٹنر کا سامنے کا معاہدہ ہے؛ وصول کنندہ طرف کے میکانکس (دستخط verify، replay protect، enqueue) /specs/ur/08-integrations-spec/ §9 میں بیان ہیں۔

12.1 واقعات

واقعہ ٹرگر عام صارف
ticket.created کسی پارٹنر کی کمپنی کی طرف سے/کے لیے نیا ٹکٹ درج۔ پارٹنر CRM۔
ticket.assigned ٹکٹ کسی محکمے/شعبے کو تفویض۔ پارٹنر۔
ticket.status_changed کوئی بھی حیثیت ٹرانزیشن (triaged، in_progress، resolved، closed، reopened، appealed)۔ پارٹنر۔
ticket.escalated اسکیلیشن لیڈر درجہ فائر ہوا۔ پارٹنر + نگرانی ڈیش بورڈ۔
ticket.resolved Resolution-proof گیٹ پورا ہوا۔ پارٹنر۔
ticket.closed آٹو کلوز یا کمپنی قبول۔ پارٹنر۔
ticket.message_appended عوامی پیغام شامل کیا گیا (کمپنی یا محکمے کی طرف سے)۔ پارٹنر۔
mom.published ٹکٹ پر MoM شائع ہوا۔ پارٹنر۔
organization.verified بیک گراؤنڈ چیکس کامیاب → تصدیق شدہ بیج۔ پارٹنر۔
organization.on_hold بیک گراؤنڈ چیک ناکام → on hold + اپیل۔ پارٹنر۔

12.2 ترسیل کا معاہدہ

12.3 HMAC-signed payload نمونہ

POST https://partner.example.org/sitp/webhook
Content-Type: application/json
X-SITP-Event: ticket.status_changed
X-SITP-Signature: t=1752752322,v1=5b1c3729d4f8a2e6b0c1d9e7f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0f1a2
X-SITP-Delivery: dlv_01HZX9F8K7P4N2Q3R6STV8WXZ
X-Request-Id: req_01HZX9F8K7P4N2Q3R6STV8WXAD

{
  "eventId": "evt_01HZX9F8K7P4N2Q3R6STV8WXAB",
  "eventType": "ticket.status_changed",
  "occurredAt": "2026-07-17T09:38:42.000Z",
  "version": "1",
  "data": {
    "ticketId": "SITP-2026-SRB-000128",
    "companyId": "cmp_01HZX7K4P9N2Q3R6STV8WXYPJ",
    "previousStatus": "new",
    "status": "assigned",
    "assignedTo": { "dept": "SRB", "section": "Refunds" },
    "sla": { "responseBy": "2026-07-19T09:00:00Z" },
    "portalUrl": "https://sindhitportal.maahir.io/tickets/SITP-2026-SRB-000128"
  },
  "delivery": { "deliveryId": "dlv_01HZX9F8K7P4N2Q3R6STV8WXZ", "attempt": 1 }
}

Verify کرنے کا pseudocode (پارٹنر طرف):

t, v1 = parse(X-SITP-Signature)            # "1752752322", "5b1c..."
if abs(now() - t) > 300: reject            # replay window
expected = HMAC_SHA256(secret, t + "." + raw_request_body)
if not constant_time_eq(expected, v1): reject
event = JSON.parse(raw_request_body)
if seen(event.eventId): ignore              # idempotency
handle(event)

دستخط SITP کے ذریعے HMAC_SHA256(secret, "<t>.<rawRequestBody>") کے طور پر compute ہوتا ہے اور v1 کے طور پر hex-encode ہوتا ہے۔


13. SDK اور Codegen منصوبہ

SITP کی OpenAPI 3.1 دستاویز کلائنٹ SDK پیدا کرنے کا واحد input ہے۔ منصوبہ:

چینل جنریٹر آؤٹ پٹ حیثیت
TypeScript / browser openapi-typescript + openapi-fetch Type-safe fetch کلائنٹ جو Next.js پورٹل استعمال کرتا ہے۔ Phase 1۔
TypeScript / Node @hey-api/openapi-ts (یا openapi-generator-cli typescript-axios) پارٹنر SDK جو private npm scope پر شائع ہو۔ Phase 1۔
Python openapi-generator-cli python پارٹنر SDK (PyPI) — تحقیق/ڈیٹا پارٹنرز کی ترجیح۔ Phase 2۔
React Native TS کلائنٹ کو دوبارہ استعمال۔ Phase 4۔
Postman / Bruno OpenAPI سے auto-پیدا کردہ collection۔ پارٹنر آن بورڈنگ پیک۔ Phase 1۔
Mock server OpenAPI دستاویز سے prism (Stoplight)۔ سینڈ باکس معاہدہ ٹیسٹنگ (§15)۔ Phase 1۔

ضابطے:


14. Deprecation پالیسی

14.1 Lifecycle

ہر API عنصر (endپوائنٹ، فیلڈ، پیرامیٹر، enum قدر، واقعہ) ان مراحل سے گزرتا ہے:

experimental → current → deprecated → sunset → removed

14.2 کیا توڑنے والی ہے (نیا میجر لازمی)

14.3 کیا غیر توڑنے والی ہے (in-version جاری)

14.4 Timelines


15. سینڈ باکس اور ٹیسٹ ماحول

ایک مخصوص Sینڈ باکس ماحول پارٹنرز کو پروڈکشن ڈیٹا کو چھوئے بغیر بنانے اور ٹیسٹ کرنے کی سہولت دیتا ہے۔

پہلو سینڈ باکس پروڈکشن
بیس URL https://sandbox.sindhitportal.maahir.io/api/v1 https://sindhitportal.maahir.io/api/v1
ڈیٹا الگ ڈیٹا بیس؛ synthetic کمپنیوں، ٹکٹس، محکموں سے seeded۔ حقیقی۔
Integrations Mocked۔ NADRA/SECP/FBR/SRB/PSEB canned جوابات لوٹاتے ہیں (ایڈاپٹر mock موڈ کے مطابق)۔ Mailjet/SMS/WhatsApp ایک اندرونی mailbox کی طرف divert ہوتے ہیں — سینڈ باکس سے کوئی حقیقی ای میل/SMS نہیں نکلتا۔ Live۔
ٹوکنز Self-service پارٹنر کنسول؛ client secrets آزادی سے rotated۔ Vetted۔
ریٹ لمٹس وہی درجے، کم ceilings (tunable)۔ §4.1 کے مطابق۔
ویب ہوکس پارٹنر endپوائنٹس سینڈ باکس سے واقعات وصول کرتے ہیں؛ پارٹنرز offline معاہدہ ٹیسٹنگ کے لیے mock server (prism) بھی استعمال کر سکتے ہیں۔ Live۔
OpenAPI سینڈ باکس host پر /api/v1/openapi.json۔ /api/v1/openapi.json۔

15.1 ٹیسٹ ڈیٹا

15.2 معاہدہ ٹیسٹنگ


16. مشاودہ پذیری — corelation IDs

ہر درخواست — کامیاب یا ناکام — ایک corelation آئی ڈی کے ذریعے end-to-end قابلِ سراغ ہے۔

ہیڈر سمت مقصد
X-Request-Id In (optional) / Out (ہمیشہ) کلائنٹ کی فراہم کردہ یا SITP کا پیدا کردہ؛ جواب پر echoed اور ہر log لائن، OTel span، اور audit_logs.request_id میں thread کیا (/specs/ur/05-data-model/ §3.10 کے مطابق)۔
X-Correlation-Id In (optional) / Out (اگر دی گئی) ایک upstream آئی ڈی carry کرتا ہے جب SITP خود کسی اور نظام (مثلاً، ایک والد حکومتی پورٹل) کے ذریعے کالا جائے۔
Traceparent (W3C) In/Out معیاری W3C trace context؛ SITP ایک OTel participant ہے اور trace کو انضمام ایڈاپٹرز تک propagate کرتا ہے (/specs/ur/08-integrations-spec/ §11 میں NFR-INT-008 کے مطابق)۔

روےہ:


17. درخواست Lifecycle (end-to-end)

ڈایاگرام ایک واحد تصدیق شدہ تحریر — POST /tickets — کا مکمل lifecycle دکھاتا ہے، پارٹنر کی HTTP کال سے ہر cross-cutting تشویش کے ذریعے آخری جواب تک۔

sequenceDiagram autonumber participant P as Partner app participant GW as nginx / API gateway participant API as NestJS API (controller) participant MW as Cross-cutting middleware<br/>(cors · ratelimit · auth · idempotency · audit · otel) participant DOM as Domain module<br/>(TicketsService) participant INT as Integration layer<br/>(adapters · resilience · DLQ) participant DB as MariaDB participant Q as BullMQ participant WH as Webhook dispatcher P->>GW: POST /api/v1/tickets\nAuthorization, Idempotency-Key, X-Request-Id GW->>API: forward (+ mints traceparent if absent) API->>MW: enter middleware chain MW->>MW: ratelimit check (429 → problem+json) MW->>MW: verify bearer token + scope (401/403 → problem+json) MW->>MW: idempotency lookup (cache hit → replay original response) MW->>MW: validate body (422 → problem+json) MW->>DOM: createTicket(dto, actor) DOM->>DB: BEGIN; insert ticket (tracking_id generated) DOM->>INT: route/notification calls (queued, idempotent) INT->>Q: enqueue (SLA timer, notifications, e-Office push) DOM->>DB: COMMIT; write audit_logs + ticket_history DOM-->>API: Ticket entity API->>WH: enqueue ticket.created event API-->>MW: build envelope {data, meta, links} MW-->>GW: 201 Created (+ X-Request-Id, rate-limit headers) GW-->>P: 201 Created, Location header Note over WH,INT: Async fan-out (after response):<br/>notifications, webhooks, SLA clock, registry checks WH->>P: POST <partner webhook URL> (signed, retried)

تحریری وضاحت۔ ایک پارٹنر POST /tickets ایک Authorization bearer، ایک Idempotency-Key، اور (اختیاری طور پر) ایک X-Request-Id کے ساتھ جاری کرتا ہے۔ nginx گیٹ وے کال forward کرتا ہے، اور کوئی traceparent موجود نہ ہو تو W3C traceparent تیار کرتا ہے۔ NestJS کے اندر، cross-cutting middleware chain ایک مقرر ترتیب میں چلتا ہے: CORS → rate limit → authentication → authorization (scope/role) → idempotency lookup → request validation → audit/OTel span open۔ کوئی بھی ناکامی اصل X-Request-Id رکھنے والے RFC 7807 problem دستاویز کے ساتھ short-circuit ہو جاتی ہے۔ اگر idempotency کلید 24 گھنٹوں کے اندر دیکھی گئی ہو اور payload مطابقت رکھتا ہو، تو اصل جواب verbatim دوبارہ چلایا جاتا ہے اور کوئی ڈومین کام نہیں چلتا۔ cache miss پر، کنٹرولر validated DTO کو TicketsService کے حوالے کرتا ہے، جو ایک MariaDB ٹرانزیکشن کھولتا ہے، SITP-YYYY-DEPT-NNNNNN ٹریکنگ آئی ڈی پیدا کرتا ہے، ٹکٹ insert کرتا ہے، ایک ticket_history قطار اور ایک audit_logs قطار لکھتا ہے، اور side-effects (SLA کلاک start، notifications، اختیاری e-Office فائل push، registry تصدیقی jobs) کو BullMQ میں enqueue کرتا ہے — یہ ٹرانزیکشن commit ہونے کے بعد چلتے ہیں تاکہ جواب کبھی بیرونی latency سے block نہ ہو۔ ٹرانزیکشن commit ہوتا ہے، کنٹرولر نیا ٹکٹ {data, meta, links} لفافے میں لپیٹتا ہے، middleware ریٹ لمٹ اور version ہیڈرز attach کرتا ہے، اور گیٹ وے نیے وسیلے کی طرف اشارہ کرتے ہوئے Location ہیڈر کے ساتھ 201 Created لوٹاتا ہے۔ اس دوران، BullMQ workers fan out ہوتے ہیں: notifications communications ایڈاپٹرز کے ذریعے بھیجے جاتے ہیں، ticket.created ویب ہوک HMAC-signed اور deliver (اور §12.2 کے مطابق retry) ہوتا ہے، اور SLA کلاک محکمے کے کاروباری اوقات کے اندر چلنا شروع ہوتا ہے۔ ہر قدم — گیٹ وے، middleware، ڈومین، انضمام، قطار — ایک OTel span emit کرتا ہے جو اسی X-Request-Id کے ساتھ tag ہے، اس لیے پارٹنر کے آئی ڈی report کرنے سے ops کو Grafana/Loki میں پورا trace reconsruct مل جاتا ہے۔


18. کھلے سوالات / TBD

# شے حیثیت
1 Premium پارٹنر درجہ ceilings اور تجارتی شرائط۔ TBD (procurement)۔
2 آیا سینڈ باکس high-trust flows کی ٹیسٹنگ کے لیے synthetic NADRA بائیو میٹرک ٹوکنز بے نقاب کرے۔ NADRA mock spec کے ساتھ TBD۔
3 TS اور Python کے علاوہ final SDK زبانیں (Go؟ Java؟)۔ TBD (پارٹنر طلب)۔
4 Analytics-heavy پارٹنرز کے لیے GraphQL facet، یا صرف REST۔ TBD (Phase 2 evaluation)۔
5 عوامی read API کلید پروگرام (صرف پڑھنے کے عوامی ڈیٹا صارفین کے لیے OAuth کا ہلکا متبادل)۔ TBD۔
6 آیا POST /sandbox/reset تمام پارٹنرز کو بے نقاب ہو یا gated۔ TBD۔
7 NestJS ↔ AI مائکروسروس boundary کے لیے gRPC / protobuf اندرونی معاہدہ (اس عوامی REST دستاویز کے دائرہ کار سے باہر)۔ /specs/ur/15-tech-architecture/ دیکھیں۔

دستاویز کا اختتام۔