{"openapi":"3.1.0","info":{"title":"Nabd Open API","version":"1.0.0","description":"Live Sudanese bank, telecom, currency, and integration-event data from status.sd.","contact":{"name":"Nabd Developers","url":"https://status.sd"}},"servers":[{"url":"https://status.sd/api/open/v1","description":"Production"}],"security":[{"apiKey":[]},{"bearerAuth":[]}],"tags":[{"name":"Status","description":"Current and historical service status."},{"name":"Markets","description":"Currency and gold snapshots."},{"name":"Integration","description":"Discover webhook event names."}],"paths":{"/dashboard":{"get":{"operationId":"getDashboard","summary":"Status dashboard","description":"Returns the current status of every bank and telecom plus public app configuration. Responses are cached for 60 seconds and include an ETag.","tags":["Status"],"parameters":[{"name":"If-None-Match","in":"header","required":false,"description":"ETag from a previous response.","schema":{"type":"string"},"example":"\"8c4f…\""}],"responses":{"200":{"description":"Current dashboard snapshot.","headers":{"X-RateLimit-Limit":{"description":"Monthly request quota.","schema":{"type":"integer","example":10000}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current quota period.","schema":{"type":"integer","example":9972}},"ETag":{"description":"Snapshot entity tag.","schema":{"type":"string"}},"Cache-Control":{"description":"Private cache policy.","schema":{"type":"string","example":"private, max-age=60, stale-while-revalidate=300"}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Dashboard"},"examples":{"example":{"summary":"Dashboard snapshot","value":{"updated_at":"2026-11-08T18:42:11.000000Z","banks":[{"slug":"bank-of-khartoum","name_ar":"بنك الخرطوم","name_en":"Bank of Khartoum","logo_url":"https://status.sd/storage/banks/bok.png","since":"2026-11-08T18:42:11.000000Z","app_status":"working","android":"working","ios":"working","internal_transfer":"working","zain_recharge":"unstable","sudani_recharge":"working","mtn_recharge":"working","electricity":"working","interbank_transfer":"down","international_transfer":null,"subscriber_services":"working","device_change":"working"}],"telecoms":[{"slug":"zain","name_ar":"زين","name_en":"Zain","call":"working","internet":"unstable","recharge":"working","since":"2026-11-08T17:00:00.000000Z"}],"app":{"website_url":"https://status.sd","android_url":"https://play.google.com/store/apps/details?id=sd.status","ios_url":""}}}}}}},"304":{"description":"The snapshot has not changed. The response has no body.","headers":{"ETag":{"description":"Current entity tag.","schema":{"type":"string","example":"\"8c4f…\""}}}},"401":{"description":"The API key is missing, malformed, expired, revoked, or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorCode"},"examples":{"example":{"summary":"Invalid API key","value":{"error":"invalid_api_key"}}}}}},"402":{"description":"An active developer subscription is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorCode"},"examples":{"example":{"summary":"Subscription required","value":{"error":"subscription_required"}}}}}},"429":{"description":"The IP/key rate limit or monthly quota has been exceeded.","headers":{"Retry-After":{"description":"Seconds until a rate-limited request may be retried.","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorCode"},"examples":{"rateLimit":{"summary":"Short-term rate limit","value":{"error":"rate_limit_exceeded"}},"quota":{"summary":"Monthly quota exhausted","value":{"error":"quota_exhausted","resets_at":"2026-12-01T00:00:00Z"}}}}}},"503":{"description":"The dashboard snapshot cannot currently be read.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"},"examples":{"example":{"summary":"Dashboard unavailable","value":{"message":"Dashboard is temporarily unavailable."}}}}}}}}},"/banks/{slug}/history":{"get":{"operationId":"getBankHistory","summary":"Bank status history","description":"Returns newest-first status intervals that started today (UTC) for one bank. Older records are never exposed by the developer API.","tags":["Status"],"parameters":[{"name":"slug","in":"path","required":true,"description":"The bank's stable slug.","schema":{"type":"string"},"example":"bank-of-khartoum"},{"name":"page","in":"query","schema":{"type":"integer","minimum":1,"maximum":10000,"default":1}},{"name":"per_page","in":"query","description":"Items per page. Do not combine with `limit`.","schema":{"type":"integer","minimum":1,"maximum":100,"default":50}},{"name":"limit","in":"query","description":"Alias for `per_page`. Do not combine both.","schema":{"type":"integer","minimum":1,"maximum":100}}],"responses":{"200":{"description":"A simple-paginated list of status intervals.","headers":{"X-RateLimit-Limit":{"description":"Monthly request quota.","schema":{"type":"integer","example":10000}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current quota period.","schema":{"type":"integer","example":9972}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankHistoryPage"},"examples":{"example":{"summary":"Bank history page","value":{"data":[{"slug":"bank-of-khartoum","name_ar":"بنك الخرطوم","name_en":"Bank of Khartoum","logo_url":"https://status.sd/storage/banks/bok.png","notification_topic":"bank_of_khartoum","since":"2026-11-08T18:42:11.000000Z","app_status":"working","android":"working","ios":"working","internal_transfer":"working","zain_recharge":"unstable","sudani_recharge":"working","mtn_recharge":"working","electricity":"working","interbank_transfer":"down","international_transfer":null,"subscriber_services":"working","device_change":"working","started_at":"2026-11-08T18:42:11.000000Z","ended_at":null}],"links":{"first":"https://status.sd/api/open/v1/banks/bank-of-khartoum/history?page=1","next":null,"prev":null},"meta":{"current_page":1,"from":1,"path":"https://status.sd/api/open/v1/banks/bank-of-khartoum/history","per_page":50,"to":1}}}}}}},"401":{"description":"The API key is missing, malformed, expired, revoked, or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorCode"},"examples":{"example":{"summary":"Invalid API key","value":{"error":"invalid_api_key"}}}}}},"402":{"description":"An active developer subscription is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorCode"},"examples":{"example":{"summary":"Subscription required","value":{"error":"subscription_required"}}}}}},"404":{"description":"No bank has this slug.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"},"examples":{"example":{"summary":"Unknown bank","value":{"message":"Not Found"}}}}}},"422":{"description":"One or more pagination parameters are invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ValidationError"},"examples":{"example":{"summary":"Invalid page size","value":{"message":"The per page field must not be greater than 100.","errors":{"per_page":["The per page field must not be greater than 100."]}}}}}}},"429":{"description":"The IP/key rate limit or monthly quota has been exceeded.","headers":{"Retry-After":{"description":"Seconds until a rate-limited request may be retried.","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorCode"},"examples":{"rateLimit":{"summary":"Short-term rate limit","value":{"error":"rate_limit_exceeded"}},"quota":{"summary":"Monthly quota exhausted","value":{"error":"quota_exhausted","resets_at":"2026-12-01T00:00:00Z"}}}}}}}}},"/currency":{"get":{"operationId":"getCurrency","summary":"Currency and gold snapshot","description":"Returns the latest bank and parallel-market rates, movement direction, and the latest gold price when available.","tags":["Markets"],"responses":{"200":{"description":"Latest currency and gold data.","headers":{"X-RateLimit-Limit":{"description":"Monthly request quota.","schema":{"type":"integer","example":10000}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current quota period.","schema":{"type":"integer","example":9972}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CurrencySnapshot"},"examples":{"example":{"summary":"Market snapshot","value":{"fetched_at":"2026-11-08T18:42:11.000000Z","source_updated_at":"2026-11-08T18:40:00.000000Z","last_checked_at":"2026-11-08T18:42:11.000000Z","rates":[{"name":"US Dollar","symbol":"$","code":"USD","bank_rate":601.5,"parallel_rate":2480,"bank_direction":"stable","parallel_direction":"up","details_url":"https://status.sd/currency/usd"}],"gold":{"price":168500,"previous_price":167000,"quoted_on":"2026-11-08","fetched_at":"2026-11-08T18:42:11.000000Z","last_checked_at":"2026-11-08T18:42:11.000000Z"}}}}}}},"401":{"description":"The API key is missing, malformed, expired, revoked, or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorCode"},"examples":{"example":{"summary":"Invalid API key","value":{"error":"invalid_api_key"}}}}}},"402":{"description":"An active developer subscription is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorCode"},"examples":{"example":{"summary":"Subscription required","value":{"error":"subscription_required"}}}}}},"429":{"description":"The IP/key rate limit or monthly quota has been exceeded.","headers":{"Retry-After":{"description":"Seconds until a rate-limited request may be retried.","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorCode"},"examples":{"rateLimit":{"summary":"Short-term rate limit","value":{"error":"rate_limit_exceeded"}},"quota":{"summary":"Monthly quota exhausted","value":{"error":"quota_exhausted","resets_at":"2026-12-01T00:00:00Z"}}}}}},"503":{"description":"No currency snapshot is available.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"},"examples":{"example":{"summary":"Rates unavailable","value":{"message":"Currency rates are unavailable."}}}}}}}}},"/events":{"get":{"operationId":"listEvents","summary":"Webhook events","description":"Lists every event code that can be selected on a developer webhook.","tags":["Integration"],"responses":{"200":{"description":"Supported event codes.","headers":{"X-RateLimit-Limit":{"description":"Monthly request quota.","schema":{"type":"integer","example":10000}},"X-RateLimit-Remaining":{"description":"Requests remaining in the current quota period.","schema":{"type":"integer","example":9972}}},"content":{"application/json":{"schema":{"type":"object","required":["data"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Event"}}}},"examples":{"example":{"summary":"All events","value":{"data":[{"code":"bank.status.changed","description":"A bank service status changed."},{"code":"currency.updated","description":"Currency rates were updated."}]}}}}}},"401":{"description":"The API key is missing, malformed, expired, revoked, or invalid.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorCode"},"examples":{"example":{"summary":"Invalid API key","value":{"error":"invalid_api_key"}}}}}},"402":{"description":"An active developer subscription is required.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorCode"},"examples":{"example":{"summary":"Subscription required","value":{"error":"subscription_required"}}}}}},"429":{"description":"The IP/key rate limit or monthly quota has been exceeded.","headers":{"Retry-After":{"description":"Seconds until a rate-limited request may be retried.","schema":{"type":"integer","example":42}}},"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorCode"},"examples":{"rateLimit":{"summary":"Short-term rate limit","value":{"error":"rate_limit_exceeded"}},"quota":{"summary":"Monthly quota exhausted","value":{"error":"quota_exhausted","resets_at":"2026-12-01T00:00:00Z"}}}}}}}}}},"webhooks":{"bankStatusChanged":{"post":{"operationId":"bankStatusChanged","summary":"bank.status.changed","description":"Sent whenever one or more service statuses for a bank change.","parameters":[{"$ref":"#/components/parameters/WebhookEvent"},{"$ref":"#/components/parameters/WebhookDelivery"},{"$ref":"#/components/parameters/WebhookTimestamp"},{"$ref":"#/components/parameters/WebhookSignature"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BankStatusChangedWebhook"},"examples":{"example":{"summary":"Bank status changed","value":{"id":18431,"event":"bank.status.changed","created_at":"2026-11-08T18:42:11+00:00","data":{"bank":{"id":1,"slug":"bank-of-khartoum","name_ar":"بنك الخرطوم","name_en":"Bank of Khartoum"},"statuses":{"app_status":"working","android":"working","ios":"working","internal_transfer":"working","zain_recharge":"unstable","sudani_recharge":"working","mtn_recharge":"working","electricity":"working","interbank_transfer":"down","international_transfer":null,"subscriber_services":"working","device_change":"working"},"changed_at":"2026-11-08T18:42:11.000000Z"}}}}}}},"responses":{"200":{"description":"Return any 2xx response to acknowledge delivery.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"examples":{"example":{"summary":"Acknowledged","value":{"received":true}}}}}},"400":{"description":"Example receiver rejection; Nabd will retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"},"examples":{"example":{"summary":"Rejected","value":{"message":"Invalid signature"}}}}}}}}},"currencyUpdated":{"post":{"operationId":"currencyUpdated","summary":"currency.updated","description":"Sent after a new currency snapshot is stored.","parameters":[{"$ref":"#/components/parameters/WebhookEvent"},{"$ref":"#/components/parameters/WebhookDelivery"},{"$ref":"#/components/parameters/WebhookTimestamp"},{"$ref":"#/components/parameters/WebhookSignature"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CurrencyUpdatedWebhook"},"examples":{"example":{"summary":"Currency updated","value":{"id":18432,"event":"currency.updated","created_at":"2026-11-08T18:45:00+00:00","data":{"snapshot_id":924,"fetched_at":"2026-11-08T18:45:00.000000Z","source_updated_at":"2026-11-08T18:40:00.000000Z","rates":[{"code":"USD","bank_rate":601.5,"parallel_rate":2480}]}}}}}}},"responses":{"200":{"description":"Return any 2xx response to acknowledge delivery.","content":{"application/json":{"schema":{"type":"object","additionalProperties":true},"examples":{"example":{"summary":"Acknowledged","value":{"received":true}}}}}},"400":{"description":"Example receiver rejection; Nabd will retry.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Message"},"examples":{"example":{"summary":"Rejected","value":{"message":"Invalid signature"}}}}}}}}}},"components":{"securitySchemes":{"apiKey":{"type":"apiKey","in":"header","name":"X-API-Key","description":"Your live developer key."},"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"API key","description":"The same developer key as a bearer token."}},"parameters":{"WebhookEvent":{"name":"X-StatusSD-Event","in":"header","required":true,"schema":{"type":"string"},"example":"bank.status.changed"},"WebhookDelivery":{"name":"X-StatusSD-Delivery","in":"header","required":true,"schema":{"type":"string"},"example":"18431"},"WebhookTimestamp":{"name":"X-StatusSD-Timestamp","in":"header","required":true,"schema":{"type":"string"},"example":"1794163331"},"WebhookSignature":{"name":"X-StatusSD-Signature","in":"header","required":true,"schema":{"type":"string"},"example":"sha256=9803f…"}},"schemas":{"ServiceStatus":{"type":["string","null"],"enum":["working","unstable","down",null],"description":"Current service state; null means no report is available."},"BankStatus":{"type":"object","required":["app_status","android","ios","internal_transfer","zain_recharge","sudani_recharge","mtn_recharge","electricity","interbank_transfer","international_transfer","subscriber_services","device_change"],"properties":{"app_status":{"$ref":"#/components/schemas/ServiceStatus"},"android":{"$ref":"#/components/schemas/ServiceStatus"},"ios":{"$ref":"#/components/schemas/ServiceStatus"},"internal_transfer":{"$ref":"#/components/schemas/ServiceStatus"},"zain_recharge":{"$ref":"#/components/schemas/ServiceStatus"},"sudani_recharge":{"$ref":"#/components/schemas/ServiceStatus"},"mtn_recharge":{"$ref":"#/components/schemas/ServiceStatus"},"electricity":{"$ref":"#/components/schemas/ServiceStatus"},"interbank_transfer":{"$ref":"#/components/schemas/ServiceStatus"},"international_transfer":{"$ref":"#/components/schemas/ServiceStatus"},"subscriber_services":{"$ref":"#/components/schemas/ServiceStatus"},"device_change":{"$ref":"#/components/schemas/ServiceStatus"}}},"Bank":{"allOf":[{"$ref":"#/components/schemas/BankStatus"},{"type":"object","required":["slug","name_ar","name_en"],"properties":{"slug":{"type":"string"},"name_ar":{"type":"string"},"name_en":{"type":"string"},"logo_url":{"type":["string","null"],"format":"uri"},"notification_topic":{"type":["string","null"]},"since":{"type":["string","null"],"format":"date-time"}}}]},"DashboardBank":{"allOf":[{"$ref":"#/components/schemas/BankStatus"},{"type":"object","required":["slug","name_ar","name_en"],"properties":{"slug":{"type":"string"},"name_ar":{"type":"string"},"name_en":{"type":"string"},"logo_url":{"type":["string","null"],"format":"uri"},"since":{"type":["string","null"],"format":"date-time"}}}]},"TelecomStatus":{"type":"object","required":["call","internet","recharge"],"properties":{"call":{"$ref":"#/components/schemas/ServiceStatus"},"internet":{"$ref":"#/components/schemas/ServiceStatus"},"recharge":{"$ref":"#/components/schemas/ServiceStatus"}}},"Telecom":{"allOf":[{"$ref":"#/components/schemas/TelecomStatus"},{"type":"object","properties":{"slug":{"type":"string"},"name_ar":{"type":"string"},"name_en":{"type":"string"},"since":{"type":["string","null"],"format":"date-time"}}}]},"Dashboard":{"type":"object","required":["updated_at","banks","telecoms","app"],"properties":{"updated_at":{"type":"string","format":"date-time"},"banks":{"type":"array","items":{"$ref":"#/components/schemas/DashboardBank"}},"telecoms":{"type":"array","items":{"$ref":"#/components/schemas/Telecom"}},"app":{"type":"object","description":"Public mobile-app configuration. The open API omits advertising controls.","additionalProperties":true}}},"BankHistoryItem":{"allOf":[{"$ref":"#/components/schemas/Bank"},{"type":"object","required":["started_at","ended_at"],"properties":{"started_at":{"type":"string","format":"date-time"},"ended_at":{"type":["string","null"],"format":"date-time"}}}]},"BankHistoryPage":{"type":"object","required":["data","links","meta"],"properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/BankHistoryItem"}},"links":{"type":"object","additionalProperties":true},"meta":{"type":"object","additionalProperties":true}}},"Gold":{"type":["object","null"],"properties":{"price":{"type":"number"},"previous_price":{"type":["number","null"]},"quoted_on":{"type":"string","format":"date"},"fetched_at":{"type":"string","format":"date-time"},"last_checked_at":{"type":"string","format":"date-time"}}},"CurrencyRate":{"type":"object","required":["name","symbol","code","bank_rate","parallel_rate"],"properties":{"name":{"type":"string"},"symbol":{"type":"string"},"code":{"type":"string"},"bank_rate":{"type":"number"},"parallel_rate":{"type":"number"},"bank_direction":{"type":["string","null"]},"parallel_direction":{"type":["string","null"]},"details_url":{"type":["string","null"],"format":"uri"}}},"CurrencySnapshot":{"type":"object","required":["fetched_at","source_updated_at","last_checked_at","rates","gold"],"properties":{"fetched_at":{"type":"string","format":"date-time"},"source_updated_at":{"type":"string","format":"date-time"},"last_checked_at":{"type":"string","format":"date-time"},"rates":{"type":"array","items":{"$ref":"#/components/schemas/CurrencyRate"}},"gold":{"$ref":"#/components/schemas/Gold"}}},"Event":{"type":"object","required":["code","description"],"properties":{"code":{"type":"string","enum":["bank.status.changed","currency.updated"]},"description":{"type":"string"}}},"ErrorCode":{"type":"object","required":["error"],"properties":{"error":{"type":"string","enum":["invalid_api_key","subscription_required","rate_limit_exceeded","quota_exhausted"]},"resets_at":{"type":"string","format":"date-time"}}},"Message":{"type":"object","required":["message"],"properties":{"message":{"type":"string"}}},"ValidationError":{"type":"object","required":["message","errors"],"properties":{"message":{"type":"string"},"errors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}}}}},"BankStatusChangedWebhook":{"type":"object","required":["id","event","created_at","data"],"properties":{"id":{"type":"integer"},"event":{"const":"bank.status.changed"},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","required":["bank","statuses","changed_at"],"properties":{"bank":{"type":"object","properties":{"id":{"type":"integer"},"slug":{"type":"string"},"name_ar":{"type":"string"},"name_en":{"type":"string"}}},"statuses":{"$ref":"#/components/schemas/BankStatus"},"changed_at":{"type":"string","format":"date-time"}}}}},"CurrencyUpdatedWebhook":{"type":"object","required":["id","event","created_at","data"],"properties":{"id":{"type":"integer"},"event":{"const":"currency.updated"},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","required":["snapshot_id","fetched_at","source_updated_at","rates"],"properties":{"snapshot_id":{"type":"integer"},"fetched_at":{"type":"string","format":"date-time"},"source_updated_at":{"type":"string","format":"date-time"},"rates":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"bank_rate":{"type":"number"},"parallel_rate":{"type":"number"}}}}}}}}}}}