{ "openapi": "3.1.0", "info": { "title": "Dancity API", "description": "Paths below match `https://api.dancity.app` + global prefix `api`. Merchant: `Authorization: Bearer dcy_live_...` and `channel: API`. App: JWT. See Guides for flows.", "version": "1.0.0" }, "servers": [ { "url": "https://api.dancity.app" } ], "tags": [ { "name": "VAS", "description": "Merchant API (`/api/external/v1`): catalog GETs (wallet, services, products, plans) and purchase routes; `channel: API` on POST buys; app education & betting where listed" }, { "name": "Products & services", "description": "One GET for services, one for products, and one per plan type, each with query filters" }, { "name": "Wallet", "description": "Get wallet by id (JWT)" }, { "name": "Transactions", "description": "Fetch your transactions and requery one by id for current status" }, { "name": "Betting", "description": "Betting funding" }, { "name": "Education", "description": "Education pins" }, { "name": "eSIM", "description": "eSIM catalog and purchase" }, { "name": "Virtual card", "description": "Cards" }, { "name": "Models", "description": "Enums and payload shapes" } ], "components": { "securitySchemes": { "DancityApiKey": { "type": "http", "scheme": "bearer", "bearerFormat": "dcy_live_...", "description": "Merchant API key from the Dancity dashboard." }, "ChannelHeader": { "type": "apiKey", "in": "header", "name": "channel", "description": "Required on VAS (merchant `/api/external/v1`) requests. Use `API` for server integrations." }, "JwtAuth": { "type": "http", "scheme": "bearer", "bearerFormat": "JWT", "description": "Bearer token from Dancity user authentication." } }, "schemas": { "SuccessEnvelope": { "type": "object", "properties": { "success": { "type": "boolean", "example": true }, "message": { "type": "string" }, "data": {} } }, "ErrorEnvelope": { "type": "object", "properties": { "statusCode": { "type": "integer" }, "message": { "type": "string" }, "error": { "type": "string" } } }, "ServiceStatus": { "type": "string", "enum": [ "SUCCESS", "FAILED", "PROCESSING", "PENDING", "CANCELLED" ], "description": "Transaction service status (internal)" }, "TranxType": { "type": "string", "enum": [ "DEBIT", "CREDIT" ] }, "PartnerWebhookPayload": { "type": "object", "description": "POST body Dancity sends to your configured HTTPS webhook URL (set in the Dancity app / API key settings).", "properties": { "event": { "type": "string", "example": "transaction.success" }, "timestamp": { "type": "string", "format": "date-time" }, "data": { "type": "object", "additionalProperties": true } } } } }, "paths": { "/api/external/v1/airtime/buy": { "post": { "tags": [ "VAS" ], "summary": "Purchase airtime", "security": [ { "DancityApiKey": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "product", "phone", "amount" ], "properties": { "product": { "type": "string", "example": "MTN Airtime" }, "phone": { "type": "string", "example": "080*******" }, "amount": { "type": "number", "minimum": 50, "maximum": 1000 }, "customerRef": { "type": "string" } } } } } }, "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Airtime purchase successful", "data": { "transactionId": "TXN-20260506-001", "status": "SUCCESS", "amount": 500, "phone": "080*******", "network": "MTN" } } } } }, "400": { "description": "Bad request", "content": { "application/json": { "example": { "success": false, "message": "Validation failed", "statusCode": 400 } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/data/buy": { "post": { "tags": [ "VAS" ], "summary": "Purchase data bundle", "security": [ { "DancityApiKey": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "plan", "phone", "wallettype" ], "properties": { "plan": { "type": "string", "description": "Data plan ID from catalogue" }, "phone": { "type": "string", "example": "080*******" }, "wallettype": { "type": "string", "example": "main" }, "customerRef": { "type": "string" } } } } } }, "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Data purchase successful", "data": { "transactionId": "TXN-20260506-002", "status": "SUCCESS", "plan": "1GB Daily", "phone": "080*******" } } } } }, "400": { "description": "Bad request", "content": { "application/json": { "example": { "success": false, "message": "Validation failed", "statusCode": 400 } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/validate": { "post": { "tags": [ "VAS" ], "summary": "Validate cable smartcard or electricity meter (merchant)", "description": "Single validation endpoint for external merchants. Set `type` to `\"cable\"` or `\"electricity\"`.", "security": [ { "DancityApiKey": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "type" ], "properties": { "type": { "type": "string", "enum": [ "cable", "electricity" ], "description": "Validation type" }, "smartcardNumber": { "type": "string", "description": "Required when type is cable" }, "cablename": { "type": "string", "description": "Required when type is cable" }, "meterNumber": { "type": "string", "description": "Required when type is electricity" }, "productName": { "type": "string", "description": "Required when type is electricity" }, "amount": { "type": "number", "description": "Required when type is electricity" }, "meterType": { "type": "string", "enum": [ "prepaid", "postpaid" ], "description": "Required when type is electricity" } } }, "examples": { "Validate cable smartcard": { "value": { "type": "cable", "smartcardNumber": "1234567890", "cablename": "DSTV" } } } } } }, "responses": { "200": { "description": "Validation successful", "content": { "application/json": { "example": { "success": true, "message": "Validation successful", "data": { "customerName": "John Doe" } } } } }, "400": { "description": "Bad request", "content": { "application/json": { "example": { "success": false, "message": "Smartcard number not found", "statusCode": 400 } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/cable/buy": { "post": { "tags": [ "VAS" ], "summary": "Purchase cable subscription", "security": [ { "DancityApiKey": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "smartcardNumber", "cableplan", "cablename", "customerName" ], "properties": { "smartcardNumber": { "type": "string" }, "cableplan": { "type": "string" }, "cablename": { "type": "string" }, "customerName": { "type": "string" }, "customerRef": { "type": "string" } } } } } }, "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Cable subscription successful", "data": { "transactionId": "TXN-20260506-003", "status": "SUCCESS", "smartcardNumber": "1234567890", "package": "DStv Compact" } } } } }, "400": { "description": "Bad request", "content": { "application/json": { "example": { "success": false, "message": "Validation failed", "statusCode": 400 } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/electricity/buy": { "post": { "tags": [ "VAS" ], "summary": "Purchase electricity (vend / postpaid)", "security": [ { "DancityApiKey": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "meterNumber", "meterType", "amount", "customerName", "address" ], "properties": { "meterNumber": { "type": "string" }, "productName": { "type": "string" }, "meterType": { "type": "string", "enum": [ "prepaid", "postpaid" ] }, "amount": { "type": "number", "minimum": 500 }, "customerName": { "type": "string" }, "address": { "type": "string" }, "customerRef": { "type": "string" } } } } } }, "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Electricity purchase processed", "data": { "transactionId": "TXN-20260506-004", "status": "SUCCESS", "token": "1234-5678-9012-3456" } } } } }, "400": { "description": "Bad request", "content": { "application/json": { "example": { "success": false, "message": "Validation failed", "statusCode": 400 } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/internet/buy": { "post": { "tags": [ "VAS" ], "summary": "Purchase internet bundle", "security": [ { "DancityApiKey": [] } ], "requestBody": { "required": true, "content": { "application/json": { "schema": { "type": "object", "required": [ "plan", "accountid", "phone" ], "properties": { "plan": { "type": "string" }, "accountid": { "type": "string" }, "phone": { "type": "string", "example": "080*******" }, "customerRef": { "type": "string" } } } } } }, "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Internet bundle purchase successful", "data": { "transactionId": "TXN-20260506-005", "status": "SUCCESS", "plan": "Spectranet 10GB" } } } } }, "400": { "description": "Bad request", "content": { "application/json": { "example": { "success": false, "message": "Validation failed", "statusCode": 400 } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/transactions": { "get": { "tags": [ "Transactions" ], "summary": "Get transactions", "description": "Fetch the authenticated user’s transactions. Use `page`, `limit`, and date range to filter. For a single row and up-to-date status, use `GET /api/external/v1/transactions/{transactionId}`.", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer", "default": 1 } }, { "name": "limit", "in": "query", "schema": { "type": "integer", "default": 10, "maximum": 100 } }, { "name": "start_date", "in": "query", "schema": { "type": "string", "format": "date-time" } }, { "name": "end_date", "in": "query", "schema": { "type": "string", "format": "date-time" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Transactions retrieved successfully", "data": { "transactions": [], "pagination": { "page": 1, "limit": 10, "total": 0, "totalPages": 0, "hasPrevious": false, "hasNext": false } } } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/services": { "get": { "tags": [ "Products & services" ], "summary": "Get services", "description": "Filter services by `name`.", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "name", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "message": "SUCCESS", "allServices": [ { "_id": "66d1ccc630a43475d74bde4d", "name": "DATA", "disable": true, "displayonmenu": true, "isutility": true, "icon": "string" } ] } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/transactions/{transactionId}": { "get": { "tags": [ "Transactions" ], "summary": "Requery transaction", "description": "Return one transaction and its current `status` by Mongo `_id` or by `transactionId`. Use to requery after a purchase or for polling. Typical `status` values include `SUCCESS`, `FAILED`, `PROCESSING`, `PENDING`, `CANCELLED`.", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "transactionId", "in": "path", "required": true, "description": "Mongo id or external `transactionId` (same path segment).", "schema": { "type": "string" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Transaction fetched", "data": { "transactionId": "TXN-20260506-001", "type": "DEBIT", "amount": 500, "status": "SUCCESS", "service": "Airtime", "phone": "080*******", "createdAt": "2026-05-06T10:00:00Z" } } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "404": { "description": "Not found", "content": { "application/json": { "example": { "success": false, "message": "Transaction not found", "statusCode": 404 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/betting/funding": { "post": { "tags": [ "Betting" ], "summary": "Fund betting account", "security": [ { "DancityApiKey": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "required": [ "product", "customerIdentifier", "amount" ], "properties": { "product": { "type": "string" }, "customerIdentifier": { "type": "string" }, "amount": { "type": "number", "minimum": 100 }, "customerRef": { "type": "string" } } } } } }, "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Betting account funded", "data": { "transactionId": "TXN-20260506-006", "status": "SUCCESS", "customerIdentifier": "user@betsite.com", "amount": 1000 } } } } }, "400": { "description": "Bad request", "content": { "application/json": { "example": { "success": false, "message": "Validation failed", "statusCode": 400 } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/education-pin/purchase": { "post": { "tags": [ "Education" ], "summary": "Purchase education pin", "security": [ { "DancityApiKey": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "required": [ "quantity", "product" ], "properties": { "quantity": { "type": "number" }, "product": { "type": "string" }, "customerRef": { "type": "string" } } } } } }, "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Education pins purchased", "data": { "transactionId": "TXN-20260506-007", "pins": [ { "pin": "****-****-****", "serial": "SN-001", "expiry": "2027-01-01" } ] } } } } }, "400": { "description": "Bad request", "content": { "application/json": { "example": { "success": false, "message": "Validation failed", "statusCode": 400 } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/education-pin/validate-product": { "post": { "tags": [ "Education" ], "summary": "Validate education product / pricing", "security": [ { "DancityApiKey": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "required": [ "product", "quantity" ], "properties": { "product": { "type": "string" }, "quantity": { "type": "number" } } } } } }, "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Product validated", "data": { "product": "WAEC Result Checker", "pricePerUnit": 4500, "quantity": 2, "total": 9000 } } } } }, "400": { "description": "Bad request", "content": { "application/json": { "example": { "success": false, "message": "Validation failed", "statusCode": 400 } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/esim/regions": { "get": { "tags": [ "eSIM" ], "summary": "eSIM regions", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "type", "in": "query", "schema": { "type": "number", "description": "1=country, 2=multi" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "eSIM regions fetched successfully", "data": { "regions": [ { "code": "ES", "name": "Spain", "type": "country", "flagUrl": null, "iso": null }, { "code": "EU-42", "name": "Europe (40+ areas)", "type": "multi-country", "flagUrl": null, "iso": null } ] } } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/esim/packages": { "get": { "tags": [ "eSIM" ], "summary": "eSIM packages for region", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "regionCode", "in": "query", "required": true, "schema": { "type": "string", "example": "NG" } }, { "name": "regionType", "in": "query", "schema": { "type": "string" } }, { "name": "type", "in": "query", "schema": { "type": "string", "enum": [ "BASE", "TOPUP" ] } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Packages fetched", "data": [ { "packageCode": "NG-1GB-7D", "name": "Nigeria 1GB 7 Days", "dataAmount": "1GB", "validity": "7 days", "price": 3000 } ] } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/esim/topup-packages": { "get": { "tags": [ "eSIM" ], "summary": "Top-up packages for ICCID", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "iccid", "in": "query", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Top-up packages fetched", "data": [ { "packageCode": "NG-1GB-7D", "name": "Nigeria 1GB Top-Up", "dataAmount": "1GB", "price": 3000 } ] } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/esim/purchase": { "post": { "tags": [ "eSIM" ], "summary": "Purchase eSIM", "security": [ { "DancityApiKey": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "required": [ "packageCode", "wallettype" ], "properties": { "packageCode": { "type": "string" }, "wallettype": { "type": "string", "example": "main" }, "customerRef": { "type": "string" } } } } } }, "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "eSIM purchased", "data": { "transactionId": "TXN-20260506-008", "status": "SUCCESS", "iccid": "8960000000000000001", "activationCode": "LPA:1$smdp.example.com$ACTIVATION-CODE" } } } } }, "400": { "description": "Bad request", "content": { "application/json": { "example": { "success": false, "message": "Validation failed", "statusCode": 400 } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/esim/my-esims": { "get": { "tags": [ "eSIM" ], "summary": "List user eSIMs", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "page", "in": "query", "schema": { "type": "integer" } }, { "name": "limit", "in": "query", "schema": { "type": "integer" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "eSIMs fetched", "data": [ { "iccid": "8960000000000000001", "status": "ACTIVE", "packageCode": "NG-1GB-7D", "expiresAt": "2026-05-13T00:00:00Z" } ] } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/esim/details/{transactionId}": { "get": { "tags": [ "eSIM" ], "summary": "eSIM details for transaction", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "transactionId", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "eSIM details fetched", "data": { "iccid": "8960000000000000001", "status": "ACTIVE", "dataRemaining": "500MB", "expiresAt": "2026-05-13T00:00:00Z" } } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/cards": { "get": { "tags": [ "Virtual card" ], "summary": "List virtual cards", "security": [ { "DancityApiKey": [] } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Cards fetched", "data": [ { "cardId": "card_abc123", "last4": "4242", "currency": "USD", "balance": 50, "status": "ACTIVE" } ] } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } }, "post": { "tags": [ "Virtual card" ], "summary": "Create virtual card", "security": [ { "DancityApiKey": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true } } } }, "responses": { "201": { "description": "Created", "content": { "application/json": { "example": { "success": true, "message": "Card created", "data": { "cardId": "card_abc123", "last4": "4242", "currency": "USD", "balance": 0, "status": "ACTIVE" } } } } }, "400": { "description": "Bad request", "content": { "application/json": { "example": { "success": false, "message": "Validation failed", "statusCode": 400 } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/cards/exchange-rate": { "get": { "tags": [ "Virtual card" ], "summary": "Card USD/FX rates", "security": [ { "DancityApiKey": [] } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Exchange rate fetched", "data": { "currency": "USD", "rate": 1620, "baseCurrency": "NGN" } } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/cards/transactions/{cardId}": { "get": { "tags": [ "Virtual card" ], "summary": "Card transactions", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "cardId", "in": "path", "required": true, "schema": { "type": "string" } }, { "name": "page", "in": "query", "schema": { "type": "integer" } }, { "name": "limit", "in": "query", "schema": { "type": "integer" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Transactions fetched", "data": { "total": 5, "transactions": [ { "id": "txn_001", "amount": 10, "currency": "USD", "description": "Netflix", "createdAt": "2026-05-01T00:00:00Z" } ] } } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/cards/wallet": { "post": { "tags": [ "Virtual card" ], "summary": "Fund or withdraw from card", "security": [ { "DancityApiKey": [] } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true } } } }, "responses": { "201": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Card funded successfully", "data": { "cardId": "card_abc123", "balance": 60, "currency": "USD" } } } } }, "400": { "description": "Bad request", "content": { "application/json": { "example": { "success": false, "message": "Validation failed", "statusCode": 400 } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/cards/{cardId}": { "get": { "tags": [ "Virtual card" ], "summary": "Get card by ID", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "cardId", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Card fetched", "data": { "cardId": "card_abc123", "last4": "4242", "currency": "USD", "balance": 50, "status": "ACTIVE" } } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } }, "put": { "tags": [ "Virtual card" ], "summary": "Update card", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "cardId", "in": "path", "required": true, "schema": { "type": "string" } } ], "requestBody": { "content": { "application/json": { "schema": { "type": "object", "additionalProperties": true } } } }, "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Card updated", "data": { "cardId": "card_abc123", "status": "FROZEN" } } } } }, "400": { "description": "Bad request", "content": { "application/json": { "example": { "success": false, "message": "Validation failed", "statusCode": 400 } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/wallet": { "get": { "tags": [ "Wallet" ], "summary": "Get wallets balance", "description": "Returns all wallets and balances for the user linked to this API key.", "security": [ { "DancityApiKey": [] } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Wallets retrieved successfully", "data": [ { "_id": "59ea65qqqqqxxxxx45zzzz7111", "user": "69ea65628bzszs42zsfdd67a2", "name": "Main Wallet", "balance": 0, "bonus": 0, "currency": "NGN", "createdAt": "2026-04-23T18:30:58.751Z", "updatedAt": "2026-04-23T18:30:58.751Z", "version": 0 } ] } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/wallet/{id}": { "get": { "tags": [ "VAS" ], "summary": "Single wallet (merchant, API key)", "description": "Wallet must belong to the API key’s linked user.", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "id", "in": "path", "required": true, "schema": { "type": "string" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/SuccessEnvelope" } } } }, "401": { "description": "Invalid API key or IP not allowlisted" }, "404": { "description": "Not found" }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/products": { "get": { "tags": [ "Products & services" ], "summary": "Get products", "description": "Filter products by `name` or `service` (service name).", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "name", "in": "query", "schema": { "type": "string" } }, { "name": "service", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "statusCode": 200, "message": "SUCCESS", "allProduct": [ { "_id": "68d846303d56536a80047ad1", "name": "1XBET", "note": "Fund 1XBET wallet", "disable": false, "service": { "_id": "68d8462d3d56536a80047a69", "name": "Betting" }, "pricingmethod": "PERCENTAGE", "price": 1.5, "min": 100, "max": 100000 } ] } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/plans/data": { "get": { "tags": [ "Products & services" ], "summary": "Get data plans", "description": "Filter by `product`.", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "product", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "message": "SUCCESS", "data": [ { "_id": "69e3b468c24a58c03a7ed3ab", "product": { "name": "MTN GIFTING", "disable": false, "service": { "name": "DATA", "disable": true }, "sortOrder": 3 }, "plansize": 40, "plansizegb": 0.04, "planvolume": "MB", "sellingprice": 50, "validity": "1 Day", "isbucketplan": false, "isHotDeal": true } ] } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/plans/cable": { "get": { "tags": [ "Products & services" ], "summary": "Get cable plans", "description": "Filter with `product`.", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "product", "in": "query", "schema": { "type": "string" } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "message": "SUCCESS", "data": [ { "_id": "66eebbe090fec69424007967", "package": "GOtv Supa Plus - monthly N16,800", "product": { "name": "GOTV" }, "sellingprice": 16800, "costprice": 16800, "commission": 0, "disable": false, "vendingmedium": "vtpass" } ] } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } }, "/api/external/v1/plans/internet": { "get": { "tags": [ "Products & services" ], "summary": "Get internet plans", "description": "Filter with `internetid`, `product`, `action`.", "security": [ { "DancityApiKey": [] } ], "parameters": [ { "name": "internetid", "in": "query", "schema": { "type": "string" } }, { "name": "product", "in": "query", "schema": { "type": "string" } }, { "name": "action", "in": "query", "schema": { "type": "string", "enum": [ "FILTER" ] } } ], "responses": { "200": { "description": "OK", "content": { "application/json": { "example": { "success": true, "message": "Internet plans fetched", "data": [ { "_id": "iplan_001", "name": "Spectranet 10GB", "product": "Spectranet", "amount": 5000 } ] } } } }, "401": { "description": "Unauthorized", "content": { "application/json": { "example": { "success": false, "message": "Invalid API key or IP not allowlisted", "statusCode": 401 } } } }, "500": { "description": "Internal server error", "content": { "application/json": { "example": { "success": false, "message": "Sorry, something went wrong. Please try again later", "statusCode": 500 } } } } } } } }, "webhooks": { "partnerTransaction": { "post": { "tags": [ "Models" ], "summary": "Inbound webhook (Dancity → your HTTPS URL)", "description": "Server-to-server POST. Verify signature as in Guides → Webhook.", "requestBody": { "content": { "application/json": { "schema": { "$ref": "#/components/schemas/PartnerWebhookPayload" } } } }, "responses": { "200": { "description": "Return 2xx to acknowledge" } } } } } }