{
    "openapi": "3.0.3",
    "info": {
        "title": "DojaPay Collection API",
        "version": "1.0.0",
        "description": "Collect payments into dedicated virtual bank accounts. Sign in with your keys for an access token, create an account per customer or order, receive an inflow.received webhook when it is paid, and confirm the payment by reference before you fulfil. Full guide: https://developers.dojapay.com/",
        "contact": {
            "email": "support@dojapay.com"
        }
    },
    "servers": [
        {
            "url": "https://api.dojapay.com/api/v1"
        }
    ],
    "tags": [
        {
            "name": "Authentication"
        },
        {
            "name": "Virtual accounts"
        },
        {
            "name": "Transactions"
        },
        {
            "name": "Wallet"
        },
        {
            "name": "Sandbox"
        }
    ],
    "security": [
        {
            "bearerAuth": []
        }
    ],
    "paths": {
        "/auth/login": {
            "post": {
                "tags": [
                    "Authentication"
                ],
                "operationId": "authLogin",
                "summary": "Sign in",
                "description": "Exchange your public and secret key for an access token. Send the keys as HTTP Basic credentials and no body. Rate limit: 5 requests per minute.",
                "security": [
                    {
                        "basicAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                },
                                "example": {
                                    "success": true,
                                    "code": "00",
                                    "message": [
                                        "Authentication successful"
                                    ],
                                    "data": {
                                        "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOi...",
                                        "refresh_token": "8b1f0c4e9a2d...",
                                        "token_type": "Bearer",
                                        "expires_in": 86400
                                    },
                                    "errors": null,
                                    "reference": "DJP-20261029101500K7Q2M9XA",
                                    "timestamp": "2026-10-29T10:15:00+01:00"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "code \"02\": The keys are wrong.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "code \"11\": The key or the merchant account is not active.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/auth/refresh": {
            "post": {
                "tags": [
                    "Authentication"
                ],
                "operationId": "authRefresh",
                "summary": "Refresh a token",
                "description": "Get a new access token without sending your secret key. Needs no access token, so it works after the old one has expired. Rate limit: 5 requests per minute.",
                "security": [],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "refresh_token"
                                ],
                                "properties": {
                                    "refresh_token": {
                                        "type": "string",
                                        "description": "The refresh token from your last sign-in or refresh."
                                    }
                                }
                            },
                            "example": {
                                "refresh_token": "8b1f0c4e9a2d..."
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                },
                                "example": {
                                    "success": true,
                                    "code": "00",
                                    "message": [
                                        "Token refreshed successfully"
                                    ],
                                    "data": {
                                        "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOi...",
                                        "refresh_token": "5d0e7a91c3f4...",
                                        "token_type": "Bearer",
                                        "expires_in": 86400
                                    },
                                    "errors": null,
                                    "reference": "DJP-20261029101500K7Q2M9XA",
                                    "timestamp": "2026-10-29T10:15:00+01:00"
                                }
                            }
                        }
                    },
                    "401": {
                        "description": "code \"02\": The refresh token is unknown, already used, or older than 30 days.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "code \"11\": The key or the merchant account is not active.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "code \"04\": refresh_token is missing.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/auth/me": {
            "get": {
                "tags": [
                    "Authentication"
                ],
                "operationId": "authMe",
                "summary": "Check your credentials",
                "description": "The merchant and key behind the current access token. Rate limit: 30 requests per minute.",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                },
                                "example": {
                                    "success": true,
                                    "code": "00",
                                    "message": [
                                        "Authenticated"
                                    ],
                                    "data": {
                                        "merchant": {
                                            "business_name": "Acme Ltd",
                                            "contact_email": "dev@acme.ng",
                                            "status": "active"
                                        },
                                        "credential": {
                                            "environment": "sandbox",
                                            "status": "active",
                                            "ip_restricted": false,
                                            "token_expires_at": "2026-10-30T10:15:00+01:00"
                                        }
                                    },
                                    "errors": null,
                                    "reference": "DJP-20261029101500K7Q2M9XA",
                                    "timestamp": "2026-10-29T10:15:00+01:00"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/auth/logout": {
            "post": {
                "tags": [
                    "Authentication"
                ],
                "operationId": "authLogout",
                "summary": "Sign out",
                "description": "Invalidate the current access token immediately. Sign in again to get a new one. Rate limit: 30 requests per minute.",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                },
                                "example": {
                                    "success": true,
                                    "code": "00",
                                    "message": [
                                        "Token invalidated"
                                    ],
                                    "data": [],
                                    "errors": null,
                                    "reference": "DJP-20261029101500K7Q2M9XA",
                                    "timestamp": "2026-10-29T10:15:00+01:00"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/virtual-account/create": {
            "post": {
                "tags": [
                    "Virtual accounts"
                ],
                "operationId": "vaCreate",
                "summary": "Create a virtual account",
                "description": "Give a customer or an order its own bank account number. Payments into it are credited to your wallet and notified to your webhook URL. Requires a live key. Rate limit: 60 requests per minute.",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "accountType",
                                    "bank",
                                    "firstName",
                                    "lastName",
                                    "email"
                                ],
                                "properties": {
                                    "accountType": {
                                        "type": "string",
                                        "enum": [
                                            "STATIC",
                                            "DYNAMIC"
                                        ],
                                        "description": "STATIC belongs to one customer and can be paid any number of times. DYNAMIC is for one order and expires."
                                    },
                                    "bank": {
                                        "type": "string",
                                        "enum": [
                                            "9psb"
                                        ],
                                        "description": "The issuing bank. Lowercase, exactly: \"9PSB\" is rejected."
                                    },
                                    "firstName": {
                                        "type": "string",
                                        "description": "Customer first name."
                                    },
                                    "lastName": {
                                        "type": "string",
                                        "description": "Customer last name."
                                    },
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "description": "Customer email address."
                                    },
                                    "bvn": {
                                        "type": "string",
                                        "pattern": "^[0-9]{11}$",
                                        "description": "Customer BVN, 11 digits. Send bvn or nin."
                                    },
                                    "nin": {
                                        "type": "string",
                                        "pattern": "^[0-9]{11}$",
                                        "description": "Customer NIN, 11 digits. Required when bvn is absent."
                                    },
                                    "amountType": {
                                        "type": "string",
                                        "enum": [
                                            "EXACT",
                                            "ANY",
                                            "HIGHEROREXACT",
                                            "LOWEROREXACT"
                                        ],
                                        "description": "What the account accepts. Required for DYNAMIC accounts."
                                    },
                                    "amount": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "In naira. Required for DYNAMIC accounts unless amountType is ANY."
                                    },
                                    "expiryHours": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 24,
                                        "description": "How long the account accepts payment, in whole hours from 1 to 24. Required for DYNAMIC accounts."
                                    }
                                }
                            },
                            "example": {
                                "accountType": "DYNAMIC",
                                "amountType": "EXACT",
                                "amount": 15000,
                                "expiryHours": 3,
                                "bank": "9psb",
                                "firstName": "Ada",
                                "lastName": "Obi",
                                "email": "ada@example.com",
                                "nin": "12345678901"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                },
                                "example": {
                                    "success": true,
                                    "code": "00",
                                    "message": [
                                        "Virtual account created/updated successfully"
                                    ],
                                    "data": {
                                        "event_type": "account.created",
                                        "account": {
                                            "name": "Ada Obi",
                                            "number": "5030012345",
                                            "type": "DYNAMIC",
                                            "bank": "9PSB",
                                            "expiry": {
                                                "date": "2026-10-29T13:15:00"
                                            }
                                        },
                                        "order": {
                                            "amount": 15000,
                                            "currency": "NGN",
                                            "description": "Acme Ltd virtual account request",
                                            "country": "NGA",
                                            "amounttype": "EXACT"
                                        },
                                        "customer": {
                                            "email": "ada@example.com",
                                            "nin": "12345678901"
                                        }
                                    },
                                    "errors": null,
                                    "reference": "DJP-20261029101500K7Q2M9XA",
                                    "timestamp": "2026-10-29T10:15:00+01:00"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "code \"11\": Signed in with a sandbox key. Use create-test.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "code \"04\": A field is missing or invalid; see errors.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/virtual-account/create-test": {
            "post": {
                "tags": [
                    "Virtual accounts"
                ],
                "operationId": "vaCreateTest",
                "summary": "Create a test account",
                "description": "The same request and response as create, with a sandbox key. You get a test account number starting 99: no bank is involved and no money can be paid into it. Pay it with Simulate a payment. Requires a sandbox key. Rate limit: 60 requests per minute.",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "accountType",
                                    "bank",
                                    "firstName",
                                    "lastName",
                                    "email"
                                ],
                                "properties": {
                                    "accountType": {
                                        "type": "string",
                                        "enum": [
                                            "STATIC",
                                            "DYNAMIC"
                                        ],
                                        "description": "STATIC belongs to one customer and can be paid any number of times. DYNAMIC is for one order and expires."
                                    },
                                    "bank": {
                                        "type": "string",
                                        "enum": [
                                            "9psb"
                                        ],
                                        "description": "The issuing bank. Lowercase, exactly: \"9PSB\" is rejected."
                                    },
                                    "firstName": {
                                        "type": "string",
                                        "description": "Customer first name."
                                    },
                                    "lastName": {
                                        "type": "string",
                                        "description": "Customer last name."
                                    },
                                    "email": {
                                        "type": "string",
                                        "format": "email",
                                        "description": "Customer email address."
                                    },
                                    "bvn": {
                                        "type": "string",
                                        "pattern": "^[0-9]{11}$",
                                        "description": "Customer BVN, 11 digits. Send bvn or nin."
                                    },
                                    "nin": {
                                        "type": "string",
                                        "pattern": "^[0-9]{11}$",
                                        "description": "Customer NIN, 11 digits. Required when bvn is absent."
                                    },
                                    "amountType": {
                                        "type": "string",
                                        "enum": [
                                            "EXACT",
                                            "ANY",
                                            "HIGHEROREXACT",
                                            "LOWEROREXACT"
                                        ],
                                        "description": "What the account accepts. Required for DYNAMIC accounts."
                                    },
                                    "amount": {
                                        "type": "number",
                                        "minimum": 0,
                                        "description": "In naira. Required for DYNAMIC accounts unless amountType is ANY."
                                    },
                                    "expiryHours": {
                                        "type": "integer",
                                        "minimum": 1,
                                        "maximum": 24,
                                        "description": "How long the account accepts payment, in whole hours from 1 to 24. Required for DYNAMIC accounts."
                                    }
                                }
                            },
                            "example": {
                                "accountType": "DYNAMIC",
                                "amountType": "EXACT",
                                "amount": 15000,
                                "expiryHours": 3,
                                "bank": "9psb",
                                "firstName": "Ada",
                                "lastName": "Obi",
                                "email": "ada@example.com",
                                "nin": "12345678901"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                },
                                "example": {
                                    "success": true,
                                    "code": "00",
                                    "message": [
                                        "Virtual account created/updated successfully"
                                    ],
                                    "data": {
                                        "event_type": "account.created",
                                        "account": {
                                            "name": "Ada Obi",
                                            "number": "5030012345",
                                            "type": "DYNAMIC",
                                            "bank": "9PSB",
                                            "expiry": {
                                                "date": "2026-10-29T13:15:00"
                                            }
                                        },
                                        "order": {
                                            "amount": 15000,
                                            "currency": "NGN",
                                            "description": "Acme Ltd virtual account request",
                                            "country": "NGA",
                                            "amounttype": "EXACT"
                                        },
                                        "customer": {
                                            "email": "ada@example.com",
                                            "nin": "12345678901"
                                        }
                                    },
                                    "errors": null,
                                    "reference": "DJP-20261029101500K7Q2M9XA",
                                    "timestamp": "2026-10-29T10:15:00+01:00"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "code \"11\": Signed in with a live key. Use create.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "code \"04\": A field is missing or invalid; see errors.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/virtual-account/details/{accountNumber}": {
            "get": {
                "tags": [
                    "Virtual accounts"
                ],
                "operationId": "vaDetails",
                "summary": "Get an account",
                "description": "One of your virtual accounts, by its account number. Rate limit: 60 requests per minute.",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "parameters": [
                    {
                        "name": "accountNumber",
                        "in": "path",
                        "required": true,
                        "description": "The 10-digit account number.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "5030012345"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                },
                                "example": {
                                    "success": true,
                                    "code": "00",
                                    "message": [
                                        "Account details retrieved successfully"
                                    ],
                                    "data": {
                                        "account_number": "5030012345",
                                        "account_name": "Ada Obi",
                                        "bank_name": "9PSB",
                                        "status": "active",
                                        "created_at": "2026-10-29T10:15:00+01:00"
                                    },
                                    "errors": null,
                                    "reference": "DJP-20261029101500K7Q2M9XA",
                                    "timestamp": "2026-10-29T10:15:00+01:00"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "code \"26\": No account with that number belongs to you.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "code \"04\": The account number is not 10 characters.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/virtual-account/list": {
            "get": {
                "tags": [
                    "Virtual accounts"
                ],
                "operationId": "vaList",
                "summary": "List accounts",
                "description": "Your virtual accounts, newest first. Rate limit: 60 requests per minute.",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "description": "Only accounts in this state.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "active",
                                "inactive",
                                "expired"
                            ]
                        }
                    },
                    {
                        "name": "bank",
                        "in": "query",
                        "required": false,
                        "description": "Only accounts at this bank, for example 9psb.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "required": false,
                        "description": "Results per page, 1 to 100. Default 20.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "required": false,
                        "description": "Page number. Default 1.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                },
                                "example": {
                                    "success": true,
                                    "code": "00",
                                    "message": [
                                        "Virtual accounts retrieved successfully"
                                    ],
                                    "data": {
                                        "data": [
                                            {
                                                "account_number": "5030012345",
                                                "account_name": "Ada Obi",
                                                "account_type": "DYNAMIC",
                                                "bank_code": "9psb",
                                                "provider": "9PSB",
                                                "status": "active",
                                                "reference_code": "...",
                                                "expires_at": "2026-10-29T13:15:00+01:00",
                                                "assigned_at": null,
                                                "created_at": "2026-10-29T10:15:00+01:00"
                                            }
                                        ],
                                        "meta": {
                                            "current_page": 1,
                                            "per_page": 20,
                                            "total": 1,
                                            "last_page": 1
                                        }
                                    },
                                    "errors": null,
                                    "reference": "DJP-20261029101500K7Q2M9XA",
                                    "timestamp": "2026-10-29T10:15:00+01:00"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/transaction/status/{reference}": {
            "get": {
                "tags": [
                    "Transactions"
                ],
                "operationId": "txStatus",
                "summary": "Confirm a payment",
                "description": "Look a payment up by its reference before you fulfil. It is confirmed when status is success. Rate limit: 60 requests per minute.",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "parameters": [
                    {
                        "name": "reference",
                        "in": "path",
                        "required": true,
                        "description": "The reference from the payment notification.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "DPY-20261029101500482913"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                },
                                "example": {
                                    "success": true,
                                    "code": "00",
                                    "message": [
                                        "Transaction status retrieved"
                                    ],
                                    "data": {
                                        "reference": "DPY-20261029101500482913",
                                        "status": "success",
                                        "settlement_status": "pending",
                                        "amount": 14919.37,
                                        "gross_amount": 15000,
                                        "currency": "NGN",
                                        "type": "credit",
                                        "channel": "virtual_account",
                                        "narration": "Virtual Account Inflow",
                                        "initiated_at": null,
                                        "completed_at": null
                                    },
                                    "errors": null,
                                    "reference": "DJP-20261029101500K7Q2M9XA",
                                    "timestamp": "2026-10-29T10:15:00+01:00"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "code \"06\": Not one of your payments. Do not fulfil.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/transaction/{reference}": {
            "get": {
                "tags": [
                    "Transactions"
                ],
                "operationId": "txShow",
                "summary": "Get a transaction",
                "description": "Everything status returns, plus the environment and when the record was created. Rate limit: 60 requests per minute.",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "parameters": [
                    {
                        "name": "reference",
                        "in": "path",
                        "required": true,
                        "description": "The transaction reference.",
                        "schema": {
                            "type": "string"
                        },
                        "example": "DPY-20261029101500482913"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                },
                                "example": {
                                    "success": true,
                                    "code": "00",
                                    "message": [
                                        "Transaction retrieved successfully"
                                    ],
                                    "data": {
                                        "reference": "DPY-20261029101500482913",
                                        "status": "success",
                                        "settlement_status": "pending",
                                        "amount": 14919.37,
                                        "gross_amount": 15000,
                                        "currency": "NGN",
                                        "type": "credit",
                                        "channel": "virtual_account",
                                        "narration": "Virtual Account Inflow",
                                        "environment": "live",
                                        "initiated_at": null,
                                        "completed_at": null,
                                        "created_at": "2026-10-29T10:15:01+01:00"
                                    },
                                    "errors": null,
                                    "reference": "DJP-20261029101500K7Q2M9XA",
                                    "timestamp": "2026-10-29T10:15:00+01:00"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "code \"06\": Not one of your transactions.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/transaction/list": {
            "get": {
                "tags": [
                    "Transactions"
                ],
                "operationId": "txList",
                "summary": "List transactions",
                "description": "Your transactions, newest first. Each payment is followed by its fee as a separate fee entry referenced <reference>-FEE; filter type=credit for payments only. Rate limit: 60 requests per minute.",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "description": "Only transactions in this state.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "success",
                                "pending",
                                "failed"
                            ]
                        }
                    },
                    {
                        "name": "type",
                        "in": "query",
                        "required": false,
                        "description": "credit for payments in, fee for the fee taken on each.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "credit",
                                "debit",
                                "fee"
                            ]
                        }
                    },
                    {
                        "name": "channel",
                        "in": "query",
                        "required": false,
                        "description": "Only transactions through this channel.",
                        "schema": {
                            "type": "string",
                            "enum": [
                                "virtual_account",
                                "transfer",
                                "card",
                                "ussd"
                            ]
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "required": false,
                        "description": "Created on or after this date, YYYY-MM-DD.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "required": false,
                        "description": "Created on or before this date, YYYY-MM-DD.",
                        "schema": {
                            "type": "string",
                            "format": "date"
                        }
                    },
                    {
                        "name": "reference",
                        "in": "query",
                        "required": false,
                        "description": "Matches any part of a reference.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "required": false,
                        "description": "Results per page, 1 to 100. Default 20.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1,
                            "maximum": 100
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "required": false,
                        "description": "Page number. Default 1.",
                        "schema": {
                            "type": "integer",
                            "minimum": 1
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                },
                                "example": {
                                    "success": true,
                                    "code": "00",
                                    "message": [
                                        "Transactions retrieved successfully"
                                    ],
                                    "data": {
                                        "data": [
                                            {
                                                "reference": "DPY-20261029101500482913",
                                                "status": "success",
                                                "settlement_status": "pending",
                                                "amount": 14919.37,
                                                "gross_amount": 15000,
                                                "currency": "NGN",
                                                "type": "credit",
                                                "channel": "virtual_account",
                                                "narration": "Virtual Account Inflow",
                                                "initiated_at": null,
                                                "completed_at": null,
                                                "created_at": "2026-10-29T10:15:01+01:00"
                                            }
                                        ],
                                        "meta": {
                                            "current_page": 1,
                                            "per_page": 20,
                                            "total": 1,
                                            "last_page": 1
                                        }
                                    },
                                    "errors": null,
                                    "reference": "DJP-20261029101500K7Q2M9XA",
                                    "timestamp": "2026-10-29T10:15:00+01:00"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "code \"04\": A filter is invalid, for example to before from.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/transaction/verify": {
            "post": {
                "tags": [
                    "Transactions"
                ],
                "operationId": "txVerify",
                "summary": "Re-verify with the bank",
                "description": "Ask the bank to re-confirm a virtual account payment. On success, returns the payment details as the bank reported them. Confirm a payment is enough for most integrations. Rate limit: 60 requests per minute.",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "reference"
                                ],
                                "properties": {
                                    "reference": {
                                        "type": "string",
                                        "description": "The payment reference."
                                    }
                                }
                            },
                            "example": {
                                "reference": "DPY-20261029101500482913"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "code \"06\": Not one of your payments, or the bank did not confirm it.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "code \"04\": The reference is missing or unknown. Or code \"17\": This payment cannot be re-verified with its bank.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/wallet/balance": {
            "get": {
                "tags": [
                    "Wallet"
                ],
                "operationId": "walletBalance",
                "summary": "Get your balance",
                "description": "Your DojaPay wallet balance, in naira. With a sandbox key, the total of your simulated payments after fees, marked \"environment\": \"sandbox\"; your real balance is never shown or touched. Rate limit: 60 requests per minute.",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                },
                                "example": {
                                    "success": true,
                                    "code": "00",
                                    "message": [
                                        "Wallet balance retrieved successfully"
                                    ],
                                    "data": {
                                        "balance": 254330.75,
                                        "currency": "NGN",
                                        "status": "active"
                                    },
                                    "errors": null,
                                    "reference": "DJP-20261029101500K7Q2M9XA",
                                    "timestamp": "2026-10-29T10:15:00+01:00"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/sandbox/simulate-payment": {
            "post": {
                "tags": [
                    "Sandbox"
                ],
                "operationId": "sandboxSimulate",
                "summary": "Simulate a payment",
                "description": "Pay one of your test accounts as if a customer had transferred to it. You get an inflow.received webhook, and the payment shows in transaction status, the transaction list and your sandbox balance, exactly as a real one would. Requires a sandbox key. Rate limit: 60 requests per minute.",
                "security": [
                    {
                        "bearerAuth": []
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "type": "object",
                                "required": [
                                    "accountNumber",
                                    "amount"
                                ],
                                "properties": {
                                    "accountNumber": {
                                        "type": "string",
                                        "description": "A test account number from create-test."
                                    },
                                    "amount": {
                                        "type": "number",
                                        "minimum": 1,
                                        "maximum": 10000000,
                                        "description": "What the customer sends, in naira. Your real fee rule is applied to it."
                                    },
                                    "senderName": {
                                        "type": "string",
                                        "description": "Who paid, as the bank would report it. Default SANDBOX SENDER."
                                    },
                                    "senderAccountNumber": {
                                        "type": "string",
                                        "pattern": "^[0-9]{10}$",
                                        "description": "The payer's account number, 10 digits."
                                    },
                                    "senderBankName": {
                                        "type": "string",
                                        "description": "The payer's bank. Default Sandbox Bank."
                                    }
                                }
                            },
                            "example": {
                                "accountNumber": "9904790966",
                                "amount": 15000,
                                "senderName": "ADA OBI"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Success",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                },
                                "example": {
                                    "success": true,
                                    "code": "00",
                                    "message": [
                                        "Sandbox payment simulated. An inflow.received webhook has been queued to your webhook URL."
                                    ],
                                    "data": {
                                        "event_type": "inflow.received",
                                        "session_id": "999999261029101500482913",
                                        "account_name": "Ada Obi",
                                        "account_number": "9904790966",
                                        "bank_name": "9PSB",
                                        "bank_code": "9PSB",
                                        "sender_bank_code": "000000",
                                        "sender_bank_name": "Sandbox Bank",
                                        "sender_account_number": "0000000000",
                                        "sender_account_name": "ADA OBI",
                                        "amount": "15000.00",
                                        "settlement_amount": 14919.37,
                                        "gross_amount": 15000,
                                        "fee_amount": 75,
                                        "charge": 80.63,
                                        "vat": 5.63,
                                        "fee_rule": {
                                            "transaction_type": "inflow_virtual_account",
                                            "charge_type": "percentage",
                                            "value": "0.50000000",
                                            "cap": null
                                        },
                                        "fee_breakdown": {
                                            "fee": 75,
                                            "vat": 5.63,
                                            "vat_rate": 0.075
                                        },
                                        "environment": "sandbox",
                                        "reference": "SBX-20261029101500731846"
                                    },
                                    "errors": null,
                                    "reference": "DJP-20261029101500K7Q2M9XA",
                                    "timestamp": "2026-10-29T10:15:00+01:00"
                                }
                            }
                        }
                    },
                    "403": {
                        "description": "code \"11\": Signed in with a live key. Real payments come from real transfers.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "404": {
                        "description": "code \"26\": No test account with that number belongs to you.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    },
                    "422": {
                        "description": "code \"25\": The account has expired. Or code \"28\": The amount breaks the account's rule, for example not exactly the amount an EXACT account expects. Or code \"04\": A field is missing or invalid; see errors.",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/Envelope"
                                }
                            }
                        }
                    }
                }
            }
        }
    },
    "components": {
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "scheme": "bearer",
                "description": "The access_token from POST /auth/login."
            },
            "basicAuth": {
                "type": "http",
                "scheme": "basic",
                "description": "Your public key as the username and your secret key as the password."
            }
        },
        "schemas": {
            "Envelope": {
                "type": "object",
                "properties": {
                    "success": {
                        "type": "boolean"
                    },
                    "code": {
                        "type": "string",
                        "description": "Two-digit result code. \"00\" is success."
                    },
                    "message": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "data": {
                        "nullable": true,
                        "description": "The result. Null when success is false."
                    },
                    "errors": {
                        "nullable": true,
                        "description": "Details when success is false."
                    },
                    "reference": {
                        "type": "string",
                        "description": "Identifies this response. Quote it to support."
                    },
                    "timestamp": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            }
        }
    }
}