{
  "openapi": "3.1.0",
  "paths": {
    "/api/v1/tenant/health": {
      "get": {
        "description": "Unauthenticated. Returns the service name, a fixed status and a timestamp.",
        "operationId": "HealthController_getHealth",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnRead"
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Liveness probe",
        "tags": [
          "tenant/health"
        ],
        "security": []
      }
    },
    "/api/v1/tenant/openapi.json": {
      "get": {
        "description": "This document, served by the API itself. Any authenticated request may read it; no scope is required.",
        "operationId": "OpenApiController_getDocument",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnRead"
          }
        ],
        "responses": {
          "200": {
            "description": "The OpenAPI document.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "OpenAPI 3.1 description of the Neo Wallet API",
        "tags": [
          "tenant/openapi"
        ],
        "x-required-scopes": []
      }
    },
    "/api/v1/tenant/customers": {
      "post": {
        "operationId": "CustomersController_onboard",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnWrite"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OnboardCustomerDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantCustomerDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Onboard a customer and open its main wallet",
        "tags": [
          "tenant/customers"
        ],
        "x-required-scopes": [
          "customers:write"
        ]
      }
    },
    "/api/v1/tenant/customers/{uid}": {
      "get": {
        "operationId": "CustomersController_getSummary",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnRead"
          },
          {
            "name": "uid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantCustomerSummaryDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Customer summary: status, KYC, wallets, identifiers, agreements, mandates",
        "tags": [
          "tenant/customers"
        ],
        "x-required-scopes": [
          "customers:read"
        ]
      }
    },
    "/api/v1/tenant/customers/{uid}/identifiers": {
      "post": {
        "operationId": "CustomerIdentifiersController_add",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnWrite"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "uid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddCustomerIdentifierDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantCustomerIdentifierDetailDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Attach an identifier to a customer",
        "tags": [
          "tenant/customers"
        ],
        "x-required-scopes": [
          "customers:write"
        ]
      },
      "get": {
        "operationId": "CustomerIdentifiersController_list",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnRead"
          },
          {
            "name": "uid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantCustomerIdentifierListDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "List a customer's identifiers, masked",
        "tags": [
          "tenant/customers"
        ],
        "x-required-scopes": [
          "customers:read"
        ]
      }
    },
    "/api/v1/tenant/customers/{uid}/identifiers/{iid}": {
      "patch": {
        "operationId": "CustomerIdentifiersController_updateVerification",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnWrite"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "uid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "iid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCustomerIdentifierDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantCustomerIdentifierDetailDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Update an identifier's verification state",
        "tags": [
          "tenant/customers"
        ],
        "x-required-scopes": [
          "customers:write"
        ]
      }
    },
    "/api/v1/tenant/customers/{uid}/agreements": {
      "post": {
        "operationId": "CustomerAgreementsController_accept",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnWrite"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "uid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AcceptCustomerAgreementDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantCustomerAgreementDetailDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Record a customer's acceptance of a document",
        "tags": [
          "tenant/customers"
        ],
        "x-required-scopes": [
          "customers:write"
        ]
      },
      "get": {
        "operationId": "CustomerAgreementsController_list",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnRead"
          },
          {
            "name": "uid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantCustomerAgreementListDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "List a customer's document acceptances",
        "tags": [
          "tenant/customers"
        ],
        "x-required-scopes": [
          "customers:read"
        ]
      }
    },
    "/api/v1/tenant/customers/{uid}/kyc-versions": {
      "post": {
        "description": "Adds a new KYC version to the customer's history; earlier versions are never edited. A move to Level 1 (`upgrade`/`downgrade` to `tier_1`, risk rating not `prohibited`) is `approved` on your declaration alone and takes effect immediately: the previous version is superseded, the customer's wallets move to the new KYC level, a wallet whose balance is above that level's maximum is flagged `credit_blocked`, and `customer.kyc_changed` is delivered to your webhook. Every other submission is `pending` until Neo Wallet's compliance review approves or rejects it (the webhook fires then). An `upgrade`/`downgrade` must move the KYC level's maximum balance in the direction it names (422). Only one pending version per customer (409).",
        "operationId": "CustomerKycVersionsController_submit",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnWrite"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "uid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SubmitCustomerKycVersionDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantCustomerKycVersionDetailDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Submit a KYC update or KYC level change for a customer",
        "tags": [
          "tenant/customers"
        ],
        "x-required-scopes": [
          "customers:write"
        ]
      }
    },
    "/api/v1/tenant/wallets/{uid}/balance": {
      "get": {
        "operationId": "WalletsController_getBalance",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnRead"
          },
          {
            "name": "uid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantWalletBalanceDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Current, held and available balance of one wallet",
        "tags": [
          "tenant/wallets"
        ],
        "x-required-scopes": [
          "wallets:read"
        ]
      }
    },
    "/api/v1/tenant/wallets/{uid}/transactions": {
      "get": {
        "description": "Only operations that have moved funds or reached a final state are listed unless `includePending=true`. For a closed period (`from`/`to` in the past) the same query returns the same rows whenever it is asked: history is never changed.",
        "operationId": "WalletsController_getTransactions",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnRead"
          },
          {
            "name": "uid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "required": false,
            "in": "query",
            "description": "Operation type code",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "required": false,
            "in": "query",
            "description": "Operation state",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "ISO-8601 instant, inclusive lower bound on createdAt",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "ISO-8601 instant, inclusive upper bound on createdAt",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "includePending",
            "required": false,
            "in": "query",
            "description": "Also list in-flight operations",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page to retrieve, 1-based.\n      <p><b>Example: </b> 1</p>\n      <p><b>Default Value: </b> 1</p>\n    ",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Records per page. Values above the maximum are clamped, not rejected.\n      <p><b>Default Value: </b> 20</p>\n      <p><b>Max Value: </b> 100</p>\n    ",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "sortBy",
            "required": false,
            "in": "query",
            "description": "Sort key. Repeat the param to sort by several fields; URL order sets precedence.\n      <p><b>Format: </b> fieldName:DIRECTION</p>\n      <p><b>Example: </b> sortBy=createdAt:DESC&sortBy=id:ASC</p>\n      <p><b>Default Value: </b> createdAt:DESC,id:DESC</p>\n      <h4>Available Fields</h4><ul><li>createdAt</li>\n<li>id</li></ul>\n      <p>Any other field is rejected with 400.</p>\n    ",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "createdAt:ASC",
                  "createdAt:DESC",
                  "id:ASC",
                  "id:DESC"
                ]
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated TenantWalletStatementRowDto",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TenantWalletStatementRowDto"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "number",
                          "example": 42
                        },
                        "page": {
                          "type": "number",
                          "example": 1
                        },
                        "limit": {
                          "type": "number",
                          "example": 20
                        },
                        "totalPages": {
                          "type": "number",
                          "example": 3
                        }
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Paginated statement of one wallet, newest first",
        "tags": [
          "tenant/wallets"
        ],
        "x-required-scopes": [
          "wallets:read"
        ]
      }
    },
    "/api/v1/tenant/wallet-credits": {
      "post": {
        "description": "Moves the amount from your prefunded balance with Neo Wallet to the customer's wallet; no payment provider is involved and the wallet is credited immediately. The wallet is credited only if the result stays within the wallet's maximum balance for the customer's KYC level and your prefunded balance covers the amount. The response state is terminal immediately and `wallet_credit.completed` is delivered to your webhook.",
        "operationId": "WalletCreditsController_create",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnWrite"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWalletCreditDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantOperationDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Credit a customer wallet from your prefunded balance",
        "tags": [
          "tenant/wallet-credits"
        ],
        "x-required-scopes": [
          "wallet-credits:write"
        ]
      }
    },
    "/api/v1/tenant/wallet-debits": {
      "post": {
        "description": "Moves the amount from the customer's wallet to the mandate's beneficiary immediately; no payment provider is involved. The `assertion` is validated on every call and must be bound to this request, with `mandateUid` as the binding target (see the Customer authentication guide); the mandate must be active, within its validity window and satisfy its amount rule, but its `frequency` is not enforced here — that applies to `POST /tenant/mandates/{uid}/debits`. The debit is all-or-nothing: available funds short of the amount are a 422 and nothing is debited. The response state is terminal immediately and `wallet_debit.completed` is delivered to your webhook.",
        "operationId": "WalletDebitsController_create",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnWrite"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateWalletDebitDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantOperationDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Debit a wallet with the customer freshly authenticated",
        "tags": [
          "tenant/wallet-debits"
        ],
        "x-required-scopes": [
          "wallet-debits:write"
        ]
      }
    },
    "/api/v1/tenant/mandates": {
      "post": {
        "description": "Records the customer's acceptance of the consent document (`agreementType = mandate`) and the mandate that cites it, together or not at all. A customer authentication assertion is required because creating a mandate is itself consent (see the Customer authentication guide). The mandate is `active` when `validFrom` has passed and `pending` until then. `beneficiaryEntityCode` must identify a beneficiary that can collect mandate debits — a business with a collection wallet at Neo Wallet, or a beneficiary Neo Wallet has configured; anything else is a 422. `replacesMandateUid` supersedes an existing mandate atomically — it is revoked with reason `superseded` and its agreement moved to `superseded`, never edited. `mandate.created` is delivered to your webhook.",
        "operationId": "MandatesController_create",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnWrite"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateMandateDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantMandateDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Register a customer's standing consent to be debited",
        "tags": [
          "tenant/mandates"
        ],
        "x-required-scopes": [
          "mandates:write"
        ]
      },
      "get": {
        "description": "Paginated. Every mandate you registered, in any status. `customerUid` narrows within your own mandates; a customer outside your account matches nothing.",
        "operationId": "MandatesController_list",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnRead"
          },
          {
            "name": "customerUid",
            "required": false,
            "in": "query",
            "description": "Customer the mandate is on",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "required": false,
            "in": "query",
            "description": "Mandate status",
            "schema": {
              "enum": [
                "pending",
                "active",
                "suspended",
                "revoked",
                "expired",
                "completed"
              ],
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page to retrieve, 1-based.\n      <p><b>Example: </b> 1</p>\n      <p><b>Default Value: </b> 1</p>\n    ",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Records per page. Values above the maximum are clamped, not rejected.\n      <p><b>Default Value: </b> 20</p>\n      <p><b>Max Value: </b> 100</p>\n    ",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "sortBy",
            "required": false,
            "in": "query",
            "description": "Sort key. Repeat the param to sort by several fields; URL order sets precedence.\n      <p><b>Format: </b> fieldName:DIRECTION</p>\n      <p><b>Example: </b> sortBy=createdAt:DESC&sortBy=id:ASC</p>\n      <p><b>Default Value: </b> createdAt:DESC,id:DESC</p>\n      <h4>Available Fields</h4><ul><li>createdAt</li>\n<li>id</li></ul>\n      <p>Any other field is rejected with 400.</p>\n    ",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "createdAt:ASC",
                  "createdAt:DESC",
                  "id:ASC",
                  "id:DESC"
                ]
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated TenantMandateDto",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TenantMandateDto"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "number",
                          "example": 42
                        },
                        "page": {
                          "type": "number",
                          "example": 1
                        },
                        "limit": {
                          "type": "number",
                          "example": 20
                        },
                        "totalPages": {
                          "type": "number",
                          "example": 3
                        }
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "List your mandates, newest first",
        "tags": [
          "tenant/mandates"
        ],
        "x-required-scopes": [
          "mandates:read"
        ]
      }
    },
    "/api/v1/tenant/mandates/{uid}": {
      "get": {
        "operationId": "MandatesController_getByUid",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnRead"
          },
          {
            "name": "uid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantMandateDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Get one of your mandates",
        "tags": [
          "tenant/mandates"
        ],
        "x-required-scopes": [
          "mandates:read"
        ]
      }
    },
    "/api/v1/tenant/mandates/{uid}/revoke": {
      "post": {
        "description": "`reason` is always required and recorded. Without `assertion` you revoke on your own authority; with one, the revocation is recorded as the customer's, and the assertion must be the mandate's customer's (see the Customer authentication guide). The mandate moves to `revoked` with `revokedAt`, the acceptance it cites moves to `revoked`, and `mandate.revoked` is delivered to your webhook. A revoked mandate is terminal — it is never reactivated; register a new one instead. Revoking a mandate that is already `revoked`, `expired` or `completed` is a 409.",
        "operationId": "MandatesController_revoke",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnWrite"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "uid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RevokeMandateDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantMandateDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Revoke one of your mandates",
        "tags": [
          "tenant/mandates"
        ],
        "x-required-scopes": [
          "mandates:write"
        ]
      }
    },
    "/api/v1/tenant/mandates/{uid}/debits": {
      "post": {
        "description": "Moves the amount from the customer's wallet to the mandate's beneficiary, like `POST /tenant/wallet-debits`, but on the standing consent alone: no authentication assertion is accepted, and the mandate's `frequency` is enforced, so a second debit inside the current period, or any debit under a `one_time` mandate that has already completed one, is a 422. Neo Wallet never schedules these — you trigger each one, and the mandate's `retryPolicy` is advisory to you. A wallet that cannot fund the debit is not an error: the 201 carries the operation in state `failed` and you also receive `wallet_debit.failed`; a failed attempt does not consume the mandate's period, so it may be retried inside it under a fresh `clientReference`.",
        "operationId": "MandateDebitsController_create",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnWrite"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          },
          {
            "name": "uid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateScheduledDebitDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantOperationDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Debit a wallet on a standing mandate, customer not present",
        "tags": [
          "tenant/mandates"
        ],
        "x-required-scopes": [
          "wallet-debits:write"
        ]
      }
    },
    "/api/v1/tenant/fees/quote": {
      "post": {
        "description": "Read-only: nothing is charged and no operation is created. The `quoteId` is valid for five minutes; pass it as `feeQuoteId` on POST /tenant/payouts to pin the charges. A wallet outside your account is a 404, identical to a nonexistent one.",
        "operationId": "FeesController_quote",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnWrite"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/TenantFeeQuoteRequestDto"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantFeeQuoteDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Quote fee, tax and total before submitting an operation",
        "tags": [
          "tenant/fees"
        ],
        "x-required-scopes": [
          "wallets:read"
        ]
      }
    },
    "/api/v1/tenant/payouts": {
      "post": {
        "description": "Sends money from a customer wallet through a payment provider, in two phases. Phase 1 is synchronous: the payment provider (`railCode`) must be active and able to send payouts, the destination a verified contact identifier of the wallet's customer, and the assertion bound to this request; the customer's KYC-level limits, the amount above which two-factor authentication is required, compliance checks and `available ≥ amount + fee + tax` are checked. The wallet is then debited for the total, with the charges itemized, and the amount is held until the payment provider answers. The response is the operation in state `processing`. Phase 2 is asynchronous: `payout.confirmed`, `payout.failed` (amount and refundable charges returned to the wallet) or `payout.uncertain` is delivered to your webhook as the payment provider reports back.",
        "operationId": "PayoutsController_create",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnWrite"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePayoutDto"
              }
            }
          }
        },
        "responses": {
          "202": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantOperationDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Pay out to the customer's own verified contact identifier",
        "tags": [
          "tenant/payouts"
        ],
        "x-required-scopes": [
          "payouts:write"
        ]
      }
    },
    "/api/v1/tenant/topup-intents": {
      "post": {
        "description": "Creates a `topup_c2b` operation in state `pending_provider` with a 12-digit `intentReference` and an `expiresAt`; no money moves yet. The payment provider (`railCode`) must be active and able to receive payments, and the customer and wallet able to receive a credit. The wallet is credited when the payment provider reports a payment carrying the reference and the exact amount before the intent expires (`topup.confirmed`); a payment that does not match is not credited and is held by Neo Wallet for reconciliation. Without a matching payment the intent fails at `expiresAt` (`topup.expired`).",
        "operationId": "TopUpIntentsController_create",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnWrite"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateTopUpIntentDto"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantTopUpIntentDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              },
              "Idempotent-Replayed": {
                "$ref": "#/components/headers/IdempotentReplayed"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/UnprocessableEntity"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Issue a top-up reference the customer quotes when paying",
        "tags": [
          "tenant/topup-intents"
        ],
        "x-required-scopes": [
          "topup-intents:write"
        ]
      }
    },
    "/api/v1/tenant/topup-intents/{uid}": {
      "get": {
        "description": "The operation detail of `GET /tenant/operations/{uid}` for a `topup_c2b` operation, plus its `intentReference` and `expiresAt`.",
        "operationId": "TopUpIntentsController_getByUid",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnRead"
          },
          {
            "name": "uid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantTopUpIntentDetailDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Get one top-up intent's status and state timeline",
        "tags": [
          "tenant/topup-intents"
        ],
        "x-required-scopes": [
          "operations:read"
        ]
      }
    },
    "/api/v1/tenant/operations": {
      "get": {
        "description": "Paginated. Every operation you created, in any state. `customerUid` and `walletUid` narrow within your own operations; a value outside your account matches nothing.",
        "operationId": "OperationsController_list",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnRead"
          },
          {
            "name": "customerUid",
            "required": false,
            "in": "query",
            "description": "Customer the operation belongs to",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "walletUid",
            "required": false,
            "in": "query",
            "description": "Wallet the operation touches (source or destination)",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "required": false,
            "in": "query",
            "description": "Operation type code",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "state",
            "required": false,
            "in": "query",
            "description": "Operation state",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "from",
            "required": false,
            "in": "query",
            "description": "ISO-8601 instant, inclusive lower bound on createdAt",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "to",
            "required": false,
            "in": "query",
            "description": "ISO-8601 instant, inclusive upper bound on createdAt",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "page",
            "required": false,
            "in": "query",
            "description": "Page to retrieve, 1-based.\n      <p><b>Example: </b> 1</p>\n      <p><b>Default Value: </b> 1</p>\n    ",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "limit",
            "required": false,
            "in": "query",
            "description": "Records per page. Values above the maximum are clamped, not rejected.\n      <p><b>Default Value: </b> 20</p>\n      <p><b>Max Value: </b> 100</p>\n    ",
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "sortBy",
            "required": false,
            "in": "query",
            "description": "Sort key. Repeat the param to sort by several fields; URL order sets precedence.\n      <p><b>Format: </b> fieldName:DIRECTION</p>\n      <p><b>Example: </b> sortBy=createdAt:DESC&sortBy=id:ASC</p>\n      <p><b>Default Value: </b> createdAt:DESC,id:DESC</p>\n      <h4>Available Fields</h4><ul><li>createdAt</li>\n<li>id</li></ul>\n      <p>Any other field is rejected with 400.</p>\n    ",
            "schema": {
              "type": "array",
              "items": {
                "type": "string",
                "enum": [
                  "createdAt:ASC",
                  "createdAt:DESC",
                  "id:ASC",
                  "id:DESC"
                ]
              }
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated TenantOperationDto",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/TenantOperationDto"
                      }
                    },
                    "meta": {
                      "type": "object",
                      "properties": {
                        "total": {
                          "type": "number",
                          "example": 42
                        },
                        "page": {
                          "type": "number",
                          "example": 1
                        },
                        "limit": {
                          "type": "number",
                          "example": 20
                        },
                        "totalPages": {
                          "type": "number",
                          "example": 3
                        }
                      }
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "List your operations, newest first",
        "tags": [
          "tenant/operations"
        ],
        "x-required-scopes": [
          "operations:read"
        ]
      }
    },
    "/api/v1/tenant/operations/{uid}": {
      "get": {
        "description": "The operation as it appears in the list, plus `timeline` (every state change in order) and, for an operation that went through a payment provider, `provider` (`null` for internal operations).",
        "operationId": "OperationsController_getByUid",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnRead"
          },
          {
            "name": "uid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantOperationDetailDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Get one operation's status and state timeline",
        "tags": [
          "tenant/operations"
        ],
        "x-required-scopes": [
          "operations:read"
        ]
      }
    },
    "/api/v1/tenant/operations/{uid}/receipt": {
      "get": {
        "description": "Amounts, fee breakdown, masked counterparty and references, plus `receiptHash` over the canonical receipt so any copy can be verified. 404 until the operation has moved funds.",
        "operationId": "OperationsController_getReceipt",
        "parameters": [
          {
            "$ref": "#/components/parameters/RequestIdOnRead"
          },
          {
            "name": "uid",
            "required": true,
            "in": "path",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TenantOperationReceiptDto"
                }
              }
            },
            "headers": {
              "X-Request-Id": {
                "$ref": "#/components/headers/XRequestId"
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/TooManyRequests"
          },
          "500": {
            "$ref": "#/components/responses/InternalError"
          },
          "503": {
            "$ref": "#/components/responses/ServiceUnavailable"
          }
        },
        "summary": "Get the receipt of one operation",
        "tags": [
          "tenant/operations"
        ],
        "x-required-scopes": [
          "operations:read"
        ]
      }
    }
  },
  "info": {
    "title": "Neo Wallet API",
    "description": "Server-to-server API for businesses integrating with Neo Wallet (`/api/v1/tenant/*`).\n\nEvery request is authenticated on its own with an API key and an Ed25519 signature (see the Authentication guide). Every write carries `Idempotency-Key` and `X-Request-Id`; every response echoes `X-Request-Id`. Errors are always `{ statusCode, message, error }` with `error` one of the declared codes. How the API changes over time is covered in the Versioning guide.",
    "version": "v1",
    "contact": {}
  },
  "tags": [],
  "servers": [],
  "components": {
    "securitySchemes": {
      "ApiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Api-Key"
      },
      "KeyId": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Key-Id"
      },
      "Timestamp": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Timestamp"
      },
      "Signature": {
        "type": "apiKey",
        "in": "header",
        "name": "X-Signature"
      }
    },
    "schemas": {
      "OnboardCustomerIdentifierDto": {
        "type": "object",
        "properties": {
          "class": {
            "type": "string",
            "enum": [
              "contact",
              "identity_document"
            ]
          },
          "type": {
            "type": "string",
            "description": "e.g. msisdn, email, national_id, passport"
          },
          "value": {
            "type": "string",
            "description": "Clear-text value; reads return it masked"
          },
          "isPrimary": {
            "type": "boolean"
          },
          "verificationStatus": {
            "type": "string",
            "enum": [
              "unverified",
              "pending",
              "verified",
              "rejected",
              "expired",
              "revoked"
            ]
          },
          "verifiedAt": {
            "type": "object",
            "description": "ISO-8601"
          },
          "issuingCountry": {
            "type": "object",
            "description": "ISO-3166-1 alpha-2"
          }
        },
        "required": [
          "class",
          "type",
          "value",
          "isPrimary",
          "verificationStatus"
        ]
      },
      "OnboardCustomerKycDto": {
        "type": "object",
        "properties": {
          "tierCode": {
            "type": "string",
            "description": "Code of an active KYC level, e.g. `tier_1`"
          },
          "reviewType": {
            "type": "string",
            "enum": [
              "onboarding"
            ]
          },
          "verificationSource": {
            "type": "string"
          },
          "sourceReference": {
            "type": "string",
            "description": "Opaque reference into your KYC system"
          },
          "evidence": {
            "type": "object",
            "additionalProperties": true
          },
          "riskRating": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "prohibited"
            ]
          }
        },
        "required": [
          "tierCode",
          "reviewType",
          "verificationSource",
          "sourceReference",
          "evidence",
          "riskRating"
        ]
      },
      "OnboardCustomerAgreementDto": {
        "type": "object",
        "properties": {
          "agreementType": {
            "type": "string",
            "enum": [
              "wallet_opening",
              "privacy",
              "fee_schedule",
              "mandate",
              "other"
            ]
          },
          "documentType": {
            "type": "string"
          },
          "documentVersion": {
            "type": "string"
          },
          "documentUri": {
            "type": "string"
          },
          "documentHash": {
            "type": "string",
            "description": "SHA-256 of the accepted document, 64 hex characters"
          },
          "acceptedAt": {
            "type": "string",
            "description": "ISO-8601"
          },
          "acceptedChannel": {
            "type": "string",
            "description": "Your channel the consent was captured in"
          },
          "evidence": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "agreementType",
          "documentType",
          "documentVersion",
          "documentUri",
          "documentHash",
          "acceptedAt",
          "acceptedChannel",
          "evidence"
        ]
      },
      "OnboardCustomerDto": {
        "type": "object",
        "properties": {
          "customerType": {
            "type": "string",
            "enum": [
              "person",
              "organization"
            ]
          },
          "displayName": {
            "type": "string"
          },
          "dateOfBirth": {
            "type": "object",
            "description": "ISO-8601 date"
          },
          "regionCode": {
            "type": "object"
          },
          "preferredLocale": {
            "type": "object",
            "description": "BCP-47; defaults to en"
          },
          "identifiers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OnboardCustomerIdentifierDto"
            }
          },
          "kyc": {
            "$ref": "#/components/schemas/OnboardCustomerKycDto"
          },
          "agreements": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OnboardCustomerAgreementDto"
            }
          },
          "rulesProfileKey": {
            "type": "object",
            "description": "The wallet profile to open the customer's wallet on; it decides what the wallet can do. Must be one your account is approved for. Omit it to use your account's default profile"
          },
          "clientReference": {
            "type": "object",
            "description": "Your own reference; stored and returned verbatim, never interpreted"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "customerType",
          "displayName",
          "identifiers",
          "kyc",
          "agreements"
        ]
      },
      "TenantCustomerIdentifierDto": {
        "type": "object",
        "properties": {
          "uid": {
            "type": "string"
          },
          "class": {
            "type": "string",
            "enum": [
              "contact",
              "identity_document"
            ]
          },
          "type": {
            "type": "string"
          },
          "maskedValue": {
            "type": "string",
            "description": "Masked; the raw value is never returned in this field"
          },
          "isPrimary": {
            "type": "boolean"
          },
          "verificationStatus": {
            "type": "string",
            "enum": [
              "unverified",
              "pending",
              "verified",
              "rejected",
              "expired",
              "revoked"
            ]
          }
        },
        "required": [
          "uid",
          "class",
          "type",
          "maskedValue",
          "isPrimary",
          "verificationStatus"
        ]
      },
      "TenantCustomerDto": {
        "type": "object",
        "properties": {
          "uid": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "restricted",
              "suspended",
              "deceased",
              "closed"
            ]
          },
          "customerType": {
            "type": "string",
            "enum": [
              "person",
              "organization"
            ]
          },
          "displayName": {
            "type": "string"
          },
          "walletUid": {
            "type": "string",
            "description": "The customer's main wallet; you can credit it immediately (POST /tenant/wallet-credits)"
          },
          "kycTierCode": {
            "type": "string",
            "description": "Code of the customer's KYC level, e.g. `tier_1`"
          },
          "rulesProfileKey": {
            "type": "string",
            "description": "The wallet profile the customer's wallet was opened on"
          },
          "identifiers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantCustomerIdentifierDto"
            }
          },
          "clientReference": {
            "type": "object",
            "nullable": true,
            "description": "Your reference, exactly as you supplied it"
          },
          "createdAt": {
            "type": "string"
          }
        },
        "required": [
          "uid",
          "status",
          "customerType",
          "displayName",
          "walletUid",
          "kycTierCode",
          "rulesProfileKey",
          "identifiers",
          "clientReference",
          "createdAt"
        ]
      },
      "TenantKycLimitsDto": {
        "type": "object",
        "properties": {
          "currency": {
            "type": "string"
          },
          "maxBalanceMinor": {
            "type": "number",
            "description": "Integer minor units (e.g. 250000 = ETB 2,500.00)"
          },
          "maxSingleTxnMinor": {
            "type": "object",
            "nullable": true,
            "description": "Minor units; null where the KYC level sets no limit"
          },
          "aggregateDailyLimitMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "monthlyOutLimitMinor": {
            "type": "object",
            "nullable": true,
            "description": "Minor units; null where the KYC level sets no limit"
          }
        },
        "required": [
          "currency",
          "maxBalanceMinor",
          "maxSingleTxnMinor",
          "aggregateDailyLimitMinor",
          "monthlyOutLimitMinor"
        ]
      },
      "TenantCustomerKycSummaryDto": {
        "type": "object",
        "properties": {
          "tierCode": {
            "type": "string",
            "description": "Code of the customer's KYC level, e.g. `tier_1`"
          },
          "tierName": {
            "type": "string",
            "description": "Display name of the KYC level"
          },
          "riskRating": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "prohibited"
            ]
          },
          "approvedAt": {
            "type": "string"
          },
          "limits": {
            "$ref": "#/components/schemas/TenantKycLimitsDto"
          }
        },
        "required": [
          "tierCode",
          "tierName",
          "riskRating",
          "approvedAt",
          "limits"
        ]
      },
      "TenantWalletBalanceSummaryDto": {
        "type": "object",
        "properties": {
          "currency": {
            "type": "string"
          },
          "currentMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "heldMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "availableMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "asOf": {
            "type": "string"
          }
        },
        "required": [
          "currency",
          "currentMinor",
          "heldMinor",
          "availableMinor",
          "asOf"
        ]
      },
      "TenantCustomerWalletSummaryDto": {
        "type": "object",
        "properties": {
          "walletUid": {
            "type": "string"
          },
          "purpose": {
            "type": "string",
            "enum": [
              "main",
              "incentive",
              "commission",
              "savings",
              "other"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "debit_blocked",
              "credit_blocked",
              "frozen",
              "dormant",
              "closed"
            ]
          },
          "currency": {
            "type": "string"
          },
          "rulesProfileKey": {
            "type": "string",
            "description": "The wallet profile the wallet was opened on"
          },
          "balance": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/TenantWalletBalanceSummaryDto"
              }
            ]
          }
        },
        "required": [
          "walletUid",
          "purpose",
          "status",
          "currency",
          "rulesProfileKey",
          "balance"
        ]
      },
      "TenantCustomerSummaryIdentifierDto": {
        "type": "object",
        "properties": {
          "uid": {
            "type": "string"
          },
          "class": {
            "type": "string",
            "enum": [
              "contact",
              "identity_document"
            ]
          },
          "type": {
            "type": "string"
          },
          "maskedValue": {
            "type": "string",
            "description": "Masked; the raw value is never returned in this field"
          },
          "isPrimary": {
            "type": "boolean"
          },
          "verificationStatus": {
            "type": "string",
            "enum": [
              "unverified",
              "pending",
              "verified",
              "rejected",
              "expired",
              "revoked"
            ]
          },
          "value": {
            "type": "object",
            "nullable": true,
            "description": "Clear text only when you hold the `customers:pii` scope and `class` is `contact`; identity documents are never unmasked. Every unmasked read is audited."
          }
        },
        "required": [
          "uid",
          "class",
          "type",
          "maskedValue",
          "isPrimary",
          "verificationStatus",
          "value"
        ]
      },
      "TenantCustomerAgreementSummaryDto": {
        "type": "object",
        "properties": {
          "agreementType": {
            "type": "string",
            "enum": [
              "wallet_opening",
              "privacy",
              "fee_schedule",
              "mandate",
              "other"
            ]
          },
          "documentVersion": {
            "type": "string"
          },
          "acceptedAt": {
            "type": "string"
          }
        },
        "required": [
          "agreementType",
          "documentVersion",
          "acceptedAt"
        ]
      },
      "TenantCustomerSummaryDto": {
        "type": "object",
        "properties": {
          "uid": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "restricted",
              "suspended",
              "deceased",
              "closed"
            ]
          },
          "customerType": {
            "type": "string",
            "enum": [
              "person",
              "organization"
            ]
          },
          "displayName": {
            "type": "string"
          },
          "kyc": {
            "nullable": true,
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/TenantCustomerKycSummaryDto"
              }
            ]
          },
          "wallets": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantCustomerWalletSummaryDto"
            }
          },
          "identifiers": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantCustomerSummaryIdentifierDto"
            }
          },
          "agreements": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantCustomerAgreementSummaryDto"
            }
          },
          "mandatesCount": {
            "type": "number",
            "description": "Number of debit mandates you hold on this customer"
          },
          "clientReference": {
            "type": "object",
            "nullable": true,
            "description": "Your reference, exactly as you supplied it"
          },
          "createdAt": {
            "type": "string"
          }
        },
        "required": [
          "uid",
          "status",
          "customerType",
          "displayName",
          "kyc",
          "wallets",
          "identifiers",
          "agreements",
          "mandatesCount",
          "clientReference",
          "createdAt"
        ]
      },
      "AddCustomerIdentifierDto": {
        "type": "object",
        "properties": {
          "class": {
            "type": "string",
            "enum": [
              "contact",
              "identity_document"
            ]
          },
          "type": {
            "type": "string",
            "description": "e.g. msisdn, email, national_id, passport"
          },
          "value": {
            "type": "string",
            "description": "Clear-text value; reads return it masked"
          },
          "isPrimary": {
            "type": "boolean",
            "description": "Demotes the previous primary of the same class"
          },
          "verificationStatus": {
            "type": "string",
            "enum": [
              "unverified",
              "pending",
              "verified",
              "rejected",
              "expired",
              "revoked"
            ]
          },
          "verifiedAt": {
            "type": "object",
            "description": "ISO-8601"
          },
          "issuingCountry": {
            "type": "object",
            "description": "ISO-3166-1 alpha-2"
          }
        },
        "required": [
          "class",
          "type",
          "value",
          "verificationStatus"
        ]
      },
      "TenantCustomerIdentifierDetailDto": {
        "type": "object",
        "properties": {
          "uid": {
            "type": "string"
          },
          "class": {
            "type": "string",
            "enum": [
              "contact",
              "identity_document"
            ]
          },
          "type": {
            "type": "string"
          },
          "maskedValue": {
            "type": "string",
            "description": "Masked; the raw value is never returned in this field"
          },
          "isPrimary": {
            "type": "boolean"
          },
          "verificationStatus": {
            "type": "string",
            "enum": [
              "unverified",
              "pending",
              "verified",
              "rejected",
              "expired",
              "revoked"
            ]
          },
          "issuingCountry": {
            "type": "object",
            "nullable": true
          },
          "verifiedAt": {
            "type": "object",
            "nullable": true
          },
          "validFrom": {
            "type": "string"
          },
          "validTo": {
            "type": "object",
            "nullable": true
          },
          "payoutEligible": {
            "type": "boolean",
            "description": "True for a verified `contact` identifier inside its validity window; only these can be a payout destination"
          }
        },
        "required": [
          "uid",
          "class",
          "type",
          "maskedValue",
          "isPrimary",
          "verificationStatus",
          "issuingCountry",
          "verifiedAt",
          "validFrom",
          "validTo",
          "payoutEligible"
        ]
      },
      "UpdateCustomerIdentifierDto": {
        "type": "object",
        "properties": {
          "verificationStatus": {
            "type": "string",
            "enum": [
              "unverified",
              "pending",
              "verified",
              "rejected",
              "expired",
              "revoked"
            ]
          },
          "verifiedAt": {
            "type": "object",
            "description": "ISO-8601; required when `verificationStatus` is `verified`",
            "nullable": true
          },
          "validTo": {
            "type": "object",
            "description": "ISO-8601; retires the identifier at this instant"
          }
        },
        "required": [
          "verificationStatus",
          "verifiedAt"
        ]
      },
      "TenantCustomerIdentifierListDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantCustomerIdentifierDetailDto"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "AcceptCustomerAgreementDto": {
        "type": "object",
        "properties": {
          "agreementType": {
            "type": "string",
            "enum": [
              "wallet_opening",
              "privacy",
              "fee_schedule",
              "mandate",
              "other"
            ]
          },
          "documentType": {
            "type": "string",
            "description": "e.g. terms, fee_schedule_v3, privacy_notice"
          },
          "documentVersion": {
            "type": "string"
          },
          "documentUri": {
            "type": "string"
          },
          "documentHash": {
            "type": "string",
            "description": "SHA-256 of the accepted document, 64 hex characters"
          },
          "acceptedAt": {
            "type": "string",
            "description": "ISO-8601"
          },
          "acceptedChannel": {
            "type": "string",
            "description": "Your channel the consent was captured in; `portal` is not accepted"
          },
          "evidence": {
            "type": "object",
            "additionalProperties": true,
            "description": "Your proof of the acceptance; never returned — `evidenceHash` stands in for it"
          }
        },
        "required": [
          "agreementType",
          "documentType",
          "documentVersion",
          "documentUri",
          "documentHash",
          "acceptedAt",
          "acceptedChannel",
          "evidence"
        ]
      },
      "TenantCustomerAgreementDetailDto": {
        "type": "object",
        "properties": {
          "uid": {
            "type": "string"
          },
          "agreementType": {
            "type": "string",
            "enum": [
              "wallet_opening",
              "privacy",
              "fee_schedule",
              "mandate",
              "other"
            ]
          },
          "documentType": {
            "type": "string"
          },
          "documentVersion": {
            "type": "string"
          },
          "documentUri": {
            "type": "string"
          },
          "documentHash": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "accepted",
              "revoked",
              "expired",
              "superseded"
            ]
          },
          "acceptedAt": {
            "type": "string"
          },
          "acceptedChannel": {
            "type": "string"
          },
          "evidenceHash": {
            "type": "string",
            "description": "SHA-256 of the canonical consent evidence"
          }
        },
        "required": [
          "uid",
          "agreementType",
          "documentType",
          "documentVersion",
          "documentUri",
          "documentHash",
          "status",
          "acceptedAt",
          "acceptedChannel",
          "evidenceHash"
        ]
      },
      "TenantCustomerAgreementListDto": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantCustomerAgreementDetailDto"
            }
          }
        },
        "required": [
          "data"
        ]
      },
      "SubmitCustomerKycVersionDto": {
        "type": "object",
        "properties": {
          "tierCode": {
            "type": "string",
            "description": "Code of an active KYC level, e.g. `tier_1`"
          },
          "reviewType": {
            "type": "string",
            "enum": [
              "upgrade",
              "downgrade",
              "periodic_review",
              "event_driven_review"
            ]
          },
          "verificationSource": {
            "type": "string"
          },
          "sourceReference": {
            "type": "string",
            "description": "Opaque reference into your KYC system"
          },
          "evidence": {
            "type": "object",
            "additionalProperties": true,
            "description": "Your verification evidence; never returned — `evidenceHash` stands in for it"
          },
          "riskRating": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "prohibited"
            ]
          }
        },
        "required": [
          "tierCode",
          "reviewType",
          "verificationSource",
          "sourceReference",
          "evidence",
          "riskRating"
        ]
      },
      "TenantCustomerKycVersionDetailDto": {
        "type": "object",
        "properties": {
          "uid": {
            "type": "string"
          },
          "customerUid": {
            "type": "string"
          },
          "tierCode": {
            "type": "string",
            "description": "Code of the KYC level this version asserts"
          },
          "reviewType": {
            "type": "string",
            "enum": [
              "upgrade",
              "downgrade",
              "periodic_review",
              "event_driven_review"
            ]
          },
          "state": {
            "type": "string",
            "enum": [
              "pending",
              "approved",
              "rejected",
              "expired",
              "superseded"
            ],
            "description": "`approved` when your assertion is accepted outright (a move to Level 1); otherwise `pending` until Neo Wallet's compliance review decides, announced by the `customer.kyc_changed` webhook"
          },
          "verificationSource": {
            "type": "string"
          },
          "sourceReference": {
            "type": "string",
            "nullable": true
          },
          "riskRating": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "prohibited"
            ],
            "nullable": true
          },
          "evidenceHash": {
            "type": "string",
            "description": "SHA-256 of the canonical evidence JSON"
          },
          "effectiveFrom": {
            "type": "string",
            "nullable": true,
            "description": "Set when the version is approved"
          },
          "createdAt": {
            "type": "string"
          }
        },
        "required": [
          "uid",
          "customerUid",
          "tierCode",
          "reviewType",
          "state",
          "verificationSource",
          "sourceReference",
          "riskRating",
          "evidenceHash",
          "effectiveFrom",
          "createdAt"
        ]
      },
      "TenantWalletBalanceDto": {
        "type": "object",
        "properties": {
          "walletUid": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "currentMinor": {
            "type": "number",
            "description": "Integer minor units (e.g. 250000 = ETB 2,500.00)"
          },
          "heldMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "availableMinor": {
            "type": "number",
            "description": "Minor units; the only figure a debit is authorized against"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "debit_blocked",
              "credit_blocked",
              "frozen",
              "dormant",
              "closed"
            ]
          },
          "asOf": {
            "type": "string",
            "description": "When the balance last changed"
          }
        },
        "required": [
          "walletUid",
          "currency",
          "currentMinor",
          "heldMinor",
          "availableMinor",
          "status",
          "asOf"
        ]
      },
      "TenantWalletStatementRowDto": {
        "type": "object",
        "properties": {
          "operationUid": {
            "type": "string"
          },
          "amountMinor": {
            "type": "number",
            "description": "Integer minor units (e.g. 250000 = ETB 2,500.00)"
          },
          "feeMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "taxMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "direction": {
            "type": "string",
            "enum": [
              "inbound",
              "outbound"
            ],
            "description": "Relative to the wallet in the path"
          },
          "state": {
            "type": "string",
            "description": "Operation state: `created`, `awaiting_authorization`, `authorized`, `held`, `processing`, `pending_provider`, `confirmed`, `failed`, `reversed` or `completed`"
          },
          "clientReference": {
            "type": "object",
            "nullable": true,
            "description": "Your reference, exactly as you supplied it"
          },
          "counterpartyHint": {
            "type": "object",
            "nullable": true,
            "description": "Masked; never the clear counterparty"
          },
          "createdAt": {
            "type": "string"
          },
          "completedAt": {
            "type": "object",
            "nullable": true
          },
          "receipt": {
            "type": "string",
            "description": "API-relative path of the receipt (`GET /tenant/operations/{uid}/receipt`)"
          }
        },
        "required": [
          "operationUid",
          "amountMinor",
          "feeMinor",
          "taxMinor",
          "direction",
          "state",
          "createdAt",
          "receipt"
        ]
      },
      "CreateWalletCreditDto": {
        "type": "object",
        "properties": {
          "walletUid": {
            "type": "string",
            "description": "The wallet to credit, as returned by POST /tenant/customers"
          },
          "amountMinor": {
            "type": "number",
            "description": "Positive integer minor units (e.g. 250000 = ETB 2,500.00)",
            "minimum": 1
          },
          "currency": {
            "type": "string",
            "description": "ISO-4217; must equal the wallet's currency",
            "example": "ETB"
          },
          "clientReference": {
            "type": "string",
            "description": "Your own reference; stored and returned verbatim, never interpreted; unique within your account"
          },
          "metadata": {
            "type": "object",
            "additionalProperties": true
          }
        },
        "required": [
          "walletUid",
          "amountMinor",
          "currency",
          "clientReference"
        ]
      },
      "TenantOperationLinksDto": {
        "type": "object",
        "properties": {
          "self": {
            "type": "string",
            "description": "API-relative path of this operation (`GET /tenant/operations/{uid}`)"
          },
          "receipt": {
            "type": "string",
            "description": "API-relative path of its receipt (`GET /tenant/operations/{uid}/receipt`)"
          }
        },
        "required": [
          "self",
          "receipt"
        ]
      },
      "TenantOperationDto": {
        "type": "object",
        "properties": {
          "uid": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "description": "Operation type, e.g. `wallet_credit`, `wallet_debit`, `payout_b2c` or `topup_c2b`"
          },
          "state": {
            "type": "string",
            "description": "Operation state: `created`, `awaiting_authorization`, `authorized`, `held`, `processing`, `pending_provider`, `confirmed`, `failed`, `reversed` or `completed`"
          },
          "amountMinor": {
            "type": "number",
            "description": "Integer minor units (e.g. 250000 = ETB 2,500.00)"
          },
          "feeMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "taxMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "currency": {
            "type": "string",
            "description": "ISO-4217"
          },
          "clientReference": {
            "type": "string",
            "nullable": true,
            "description": "Your reference, exactly as you supplied it"
          },
          "createdAt": {
            "type": "string"
          },
          "completedAt": {
            "type": "string",
            "nullable": true,
            "description": "When the operation first reached a final state"
          },
          "links": {
            "$ref": "#/components/schemas/TenantOperationLinksDto"
          }
        },
        "required": [
          "uid",
          "type",
          "state",
          "amountMinor",
          "feeMinor",
          "taxMinor",
          "currency",
          "createdAt",
          "links"
        ]
      },
      "TransactionBindingDto": {
        "type": "object",
        "properties": {
          "hash": {
            "type": "string",
            "description": "SHA-256 hex (64 characters) over the canonical string of this request"
          },
          "algorithm": {
            "type": "string",
            "enum": [
              "sha256"
            ]
          },
          "canonical": {
            "type": "string",
            "enum": [
              "customerUid|walletUid|amountMinor|currency|destinationIdentifierUid|clientReference"
            ],
            "description": "The field template hashed: the six values joined with `|`, UTF-8. The fifth is the payout destination, the mandate for a debit, or empty; `clientReference` is empty when absent."
          }
        },
        "required": [
          "hash",
          "algorithm",
          "canonical"
        ]
      },
      "AuthenticationAssertionDto": {
        "type": "object",
        "properties": {
          "customerUid": {
            "type": "string",
            "description": "The customer who authenticated"
          },
          "identifierUid": {
            "type": "object",
            "description": "The customer identifier the customer authenticated with, if known"
          },
          "assuranceLevel": {
            "type": "string",
            "enum": [
              "single_factor",
              "two_factor",
              "step_up"
            ],
            "description": "How strongly your channel authenticated the customer"
          },
          "factor1Type": {
            "type": "string",
            "description": "The first factor used, e.g. `pin`, `password`, `biometric`",
            "maxLength": 32
          },
          "factor2Type": {
            "type": "object",
            "description": "Required unless `assuranceLevel` is `single_factor`",
            "maxLength": 32
          },
          "authenticatedAt": {
            "type": "string",
            "description": "ISO-8601 — when the customer authenticated"
          },
          "expiresAt": {
            "type": "string",
            "description": "ISO-8601; by default at most 10 minutes after `authenticatedAt`. An expired assertion is refused (422)."
          },
          "channelCode": {
            "type": "string",
            "description": "Your channel the customer authenticated on",
            "maxLength": 40
          },
          "deviceHash": {
            "type": "object",
            "description": "SHA-256 hex of the device fingerprint, if your channel has one"
          },
          "sourceReference": {
            "type": "string",
            "description": "Opaque channel evidence reference (a session or login id). Presenting one again while it is live is allowed only for the same customer, and is audited.",
            "maxLength": 160
          },
          "transactionBinding": {
            "description": "Hash your channel computed over the request this assertion authorizes; a mismatch with the request received is refused",
            "allOf": [
              {
                "$ref": "#/components/schemas/TransactionBindingDto"
              }
            ]
          }
        },
        "required": [
          "customerUid",
          "assuranceLevel",
          "factor1Type",
          "authenticatedAt",
          "expiresAt",
          "channelCode",
          "sourceReference"
        ]
      },
      "CreateWalletDebitDto": {
        "type": "object",
        "properties": {
          "walletUid": {
            "type": "string",
            "description": "The wallet to debit, as returned by POST /tenant/customers"
          },
          "mandateUid": {
            "type": "string",
            "description": "An active mandate of the wallet's customer that you hold (POST /tenant/mandates); its beneficiary receives this debit"
          },
          "amountMinor": {
            "type": "number",
            "description": "Positive integer minor units (e.g. 250000 = ETB 2,500.00); must satisfy the mandate's amount rule",
            "minimum": 1
          },
          "currency": {
            "type": "string",
            "description": "ISO-4217; must equal the wallet's currency",
            "example": "ETB"
          },
          "clientReference": {
            "type": "string",
            "description": "Your own reference; stored and returned verbatim, never interpreted; unique within your account"
          },
          "assertion": {
            "description": "The customer's authentication for this debit",
            "allOf": [
              {
                "$ref": "#/components/schemas/AuthenticationAssertionDto"
              }
            ]
          }
        },
        "required": [
          "walletUid",
          "mandateUid",
          "amountMinor",
          "currency",
          "clientReference",
          "assertion"
        ]
      },
      "MandateAgreementDto": {
        "type": "object",
        "properties": {
          "documentType": {
            "type": "string",
            "description": "Kind of document accepted, e.g. `debit_mandate_terms`",
            "maxLength": 40
          },
          "documentVersion": {
            "type": "string",
            "description": "Version of the accepted document",
            "maxLength": 40
          },
          "documentUri": {
            "type": "string",
            "description": "URI of the accepted document",
            "maxLength": 500
          },
          "documentHash": {
            "type": "string",
            "description": "SHA-256 of the accepted document, 64 hex characters"
          },
          "acceptedAt": {
            "type": "string",
            "description": "When the customer accepted the document, ISO-8601"
          },
          "acceptedChannel": {
            "type": "string",
            "description": "Your channel the consent was captured in; `portal` is not accepted"
          },
          "evidence": {
            "type": "object",
            "additionalProperties": true,
            "description": "Your proof of the acceptance; hashed and stored, never returned"
          }
        },
        "required": [
          "documentType",
          "documentVersion",
          "documentUri",
          "documentHash",
          "acceptedAt",
          "acceptedChannel",
          "evidence"
        ]
      },
      "CreateMandateDto": {
        "type": "object",
        "properties": {
          "customerUid": {
            "type": "string",
            "description": "The customer giving the standing consent"
          },
          "walletUid": {
            "type": "string",
            "description": "The customer's wallet the mandate debits"
          },
          "beneficiaryEntityCode": {
            "type": "string",
            "description": "Code of the beneficiary the debits pay; it must be a beneficiary set up with Neo Wallet to collect payments",
            "maxLength": 40
          },
          "clientReference": {
            "type": "string",
            "description": "Your own reference; stored and returned verbatim, never interpreted"
          },
          "amountRule": {
            "type": "string",
            "enum": [
              "fixed",
              "up_to",
              "formula"
            ],
            "description": "How the amount of each debit is bounded"
          },
          "fixedOrMaxAmountMinor": {
            "type": "object",
            "description": "Integer minor units (e.g. 250000 = ETB 2,500.00); the exact (`fixed`) or maximum (`up_to`) debit. Required unless `amountRule` is `formula`.",
            "minimum": 1
          },
          "formula": {
            "type": "object",
            "additionalProperties": true,
            "description": "The `formula` rule's document. No schema is defined yet, so `formula` is refused (422)."
          },
          "frequency": {
            "type": "string",
            "enum": [
              "one_time",
              "daily",
              "weekly",
              "monthly",
              "on_due_date",
              "ad_hoc"
            ],
            "description": "How often the mandate may be debited"
          },
          "currency": {
            "type": "string",
            "description": "ISO-4217; must equal the wallet's currency",
            "example": "ETB"
          },
          "validFrom": {
            "type": "string",
            "description": "ISO-8601; the mandate is `pending` until then and `active` after"
          },
          "validTo": {
            "type": "object",
            "description": "ISO-8601; must be after `validFrom`. Absent = open-ended."
          },
          "retryPolicy": {
            "type": "object",
            "additionalProperties": true,
            "description": "Advisory, for your own use; Neo Wallet never schedules or retries a debit"
          },
          "agreement": {
            "description": "The consent document the customer accepted for this mandate",
            "allOf": [
              {
                "$ref": "#/components/schemas/MandateAgreementDto"
              }
            ]
          },
          "assertion": {
            "description": "The customer's authentication for giving this consent",
            "allOf": [
              {
                "$ref": "#/components/schemas/AuthenticationAssertionDto"
              }
            ]
          },
          "replacesMandateUid": {
            "type": "object",
            "description": "An existing mandate of this customer to supersede; it is revoked as this one is created"
          }
        },
        "required": [
          "customerUid",
          "walletUid",
          "beneficiaryEntityCode",
          "clientReference",
          "amountRule",
          "frequency",
          "currency",
          "validFrom",
          "agreement",
          "assertion"
        ]
      },
      "TenantMandateDto": {
        "type": "object",
        "properties": {
          "uid": {
            "type": "string"
          },
          "customerUid": {
            "type": "string"
          },
          "walletUid": {
            "type": "string"
          },
          "beneficiaryEntityCode": {
            "type": "string"
          },
          "clientReference": {
            "type": "object",
            "nullable": true,
            "description": "Your reference, exactly as you supplied it"
          },
          "amountRule": {
            "type": "string",
            "enum": [
              "fixed",
              "up_to",
              "formula"
            ]
          },
          "fixedOrMaxAmountMinor": {
            "type": "object",
            "nullable": true,
            "description": "Minor units"
          },
          "frequency": {
            "type": "string",
            "enum": [
              "one_time",
              "daily",
              "weekly",
              "monthly",
              "on_due_date",
              "ad_hoc"
            ]
          },
          "currency": {
            "type": "string"
          },
          "validFrom": {
            "type": "string"
          },
          "validTo": {
            "type": "object",
            "nullable": true
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "suspended",
              "revoked",
              "expired",
              "completed"
            ]
          },
          "agreementUid": {
            "type": "object",
            "nullable": true,
            "description": "The acceptance recorded with this mandate"
          },
          "replacesMandateUid": {
            "type": "object",
            "nullable": true,
            "description": "The mandate this one superseded"
          },
          "revokedAt": {
            "type": "object",
            "nullable": true,
            "description": "When the mandate was revoked; `null` unless `status` is `revoked`"
          },
          "createdAt": {
            "type": "string"
          }
        },
        "required": [
          "uid",
          "customerUid",
          "walletUid",
          "beneficiaryEntityCode",
          "clientReference",
          "amountRule",
          "fixedOrMaxAmountMinor",
          "frequency",
          "currency",
          "validFrom",
          "validTo",
          "status",
          "agreementUid",
          "replacesMandateUid",
          "revokedAt",
          "createdAt"
        ]
      },
      "RevokeMandateDto": {
        "type": "object",
        "properties": {
          "reason": {
            "type": "string",
            "description": "Why the mandate is revoked; recorded on the mandate and the audit trail",
            "maxLength": 500
          },
          "assertion": {
            "description": "The customer's authentication when you revoke on the customer's behalf; it must be for the mandate's customer. Omit when you revoke on your own authority.",
            "allOf": [
              {
                "$ref": "#/components/schemas/AuthenticationAssertionDto"
              }
            ]
          }
        },
        "required": [
          "reason"
        ]
      },
      "CreateScheduledDebitDto": {
        "type": "object",
        "properties": {
          "walletUid": {
            "type": "string",
            "description": "The wallet to debit; must be the mandate's own wallet"
          },
          "amountMinor": {
            "type": "number",
            "description": "Positive integer minor units (e.g. 250000 = ETB 2,500.00); must satisfy the mandate's amount rule",
            "minimum": 1
          },
          "currency": {
            "type": "string",
            "description": "ISO-4217; must equal the wallet's currency",
            "example": "ETB"
          },
          "clientReference": {
            "type": "string",
            "description": "Your own reference; stored and returned verbatim, never interpreted; unique within your account"
          }
        },
        "required": [
          "walletUid",
          "amountMinor",
          "currency",
          "clientReference"
        ]
      },
      "TenantFeeQuoteRequestDto": {
        "type": "object",
        "properties": {
          "operationType": {
            "type": "string",
            "enum": [
              "wallet_credit",
              "wallet_debit",
              "payout_b2c",
              "topup_c2b",
              "hold",
              "safeguarding_fund",
              "client_funding_deposit",
              "settlement_sweep",
              "wallet_closure",
              "closed_balance_refund",
              "ledger_adjustment",
              "wallet_transfer"
            ],
            "description": "The operation you are about to submit. Only `wallet_credit`, `wallet_debit`, `payout_b2c` and `topup_c2b` can be quoted."
          },
          "walletUid": {
            "type": "string",
            "description": "The wallet the operation will move money on, as returned by POST /tenant/customers"
          },
          "amountMinor": {
            "type": "number",
            "description": "Positive integer minor units (e.g. 250000 = ETB 2,500.00); the operation amount before charges",
            "minimum": 1
          },
          "currency": {
            "type": "string",
            "description": "ISO-4217; must equal the wallet's currency",
            "example": "ETB"
          },
          "railCode": {
            "type": "string",
            "description": "The payment provider's code the operation will use, when it has one (payout, top-up)",
            "maxLength": 64,
            "nullable": true
          }
        },
        "required": [
          "operationType",
          "walletUid",
          "amountMinor",
          "currency"
        ]
      },
      "TenantFeeQuoteBreakdownItemDto": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string",
            "description": "The component's label in the fee rule"
          },
          "type": {
            "type": "string",
            "enum": [
              "flat",
              "percentage",
              "vat"
            ]
          },
          "amountMinor": {
            "type": "number",
            "description": "Minor units; a component that rounds to zero is listed at 0"
          },
          "refundable": {
            "type": "boolean",
            "description": "Whether a failed payout refunds this component"
          },
          "appliesToLabel": {
            "type": "string",
            "nullable": true,
            "description": "For `vat`, the label of the component it applies to"
          }
        },
        "required": [
          "label",
          "type",
          "amountMinor",
          "refundable",
          "appliesToLabel"
        ]
      },
      "TenantFeeQuoteRuleVersionDto": {
        "type": "object",
        "properties": {
          "uid": {
            "type": "string"
          },
          "ruleCode": {
            "type": "string"
          },
          "versionNo": {
            "type": "number"
          }
        },
        "required": [
          "uid",
          "ruleCode",
          "versionNo"
        ]
      },
      "TenantFeeQuoteDto": {
        "type": "object",
        "properties": {
          "quoteId": {
            "type": "string",
            "description": "Pass as `feeQuoteId` on POST /tenant/payouts to pin these charges while the quote is valid"
          },
          "operationType": {
            "type": "string",
            "enum": [
              "wallet_credit",
              "wallet_debit",
              "payout_b2c",
              "topup_c2b",
              "hold",
              "safeguarding_fund",
              "client_funding_deposit",
              "settlement_sweep",
              "wallet_closure",
              "closed_balance_refund",
              "ledger_adjustment",
              "wallet_transfer"
            ]
          },
          "walletUid": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "amountMinor": {
            "type": "number",
            "description": "Minor units — the amount quoted, as sent"
          },
          "feeMinor": {
            "type": "number",
            "description": "Minor units — the `flat` / `percentage` components"
          },
          "taxMinor": {
            "type": "number",
            "description": "Minor units — the `vat` components"
          },
          "totalMinor": {
            "type": "number",
            "description": "Minor units — `amountMinor + feeMinor + taxMinor`, what the wallet is debited"
          },
          "breakdown": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantFeeQuoteBreakdownItemDto"
            }
          },
          "ruleVersion": {
            "nullable": true,
            "description": "The fee rule version the quote was priced under; `null` for a zero-fee operation",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/TenantFeeQuoteRuleVersionDto"
              }
            ]
          },
          "railCode": {
            "type": "string",
            "nullable": true,
            "description": "The payment provider's code, as sent; `null` when none was sent"
          },
          "validUntil": {
            "type": "string",
            "description": "Instant the quote stops being honoured — five minutes from issue"
          }
        },
        "required": [
          "quoteId",
          "operationType",
          "walletUid",
          "currency",
          "amountMinor",
          "feeMinor",
          "taxMinor",
          "totalMinor",
          "breakdown",
          "ruleVersion",
          "railCode",
          "validUntil"
        ]
      },
      "CreatePayoutDto": {
        "type": "object",
        "properties": {
          "walletUid": {
            "type": "string",
            "description": "The wallet to pay out from, as returned by POST /tenant/customers"
          },
          "destinationIdentifierUid": {
            "type": "string",
            "description": "A verified contact identifier of the wallet's customer (`payoutEligible` on GET /tenant/customers/{uid}/identifiers); anything else is refused"
          },
          "amountMinor": {
            "type": "number",
            "description": "Positive integer minor units (e.g. 250000 = ETB 2,500.00); the amount the destination receives",
            "minimum": 1
          },
          "currency": {
            "type": "string",
            "description": "ISO-4217; must equal the wallet's currency",
            "example": "ETB"
          },
          "railCode": {
            "type": "string",
            "description": "The payment provider's code to pay out on; the provider must be active and support payouts",
            "maxLength": 64
          },
          "clientReference": {
            "type": "string",
            "description": "Your own reference; stored and returned verbatim, never interpreted; unique within your account"
          },
          "assertion": {
            "description": "The customer's authentication for this payout",
            "allOf": [
              {
                "$ref": "#/components/schemas/AuthenticationAssertionDto"
              }
            ]
          },
          "feeQuoteId": {
            "type": "object",
            "description": "A `quoteId` from POST /tenant/fees/quote to pin the charges to; while still valid the quoted amounts are used and must equal a fresh computation, otherwise the charges are computed fresh",
            "maxLength": 64
          }
        },
        "required": [
          "walletUid",
          "destinationIdentifierUid",
          "amountMinor",
          "currency",
          "railCode",
          "clientReference",
          "assertion"
        ]
      },
      "CreateTopUpIntentDto": {
        "type": "object",
        "properties": {
          "walletUid": {
            "type": "string",
            "description": "The wallet the top-up credits, as returned by POST /tenant/customers"
          },
          "amountMinor": {
            "type": "number",
            "description": "Positive integer minor units (e.g. 250000 = ETB 2,500.00); the exact amount the payer must pay in",
            "minimum": 1
          },
          "currency": {
            "type": "string",
            "description": "ISO-4217; must equal the wallet's currency",
            "example": "ETB"
          },
          "railCode": {
            "type": "string",
            "description": "The payment provider's code the payer will pay through; the provider must be active and accept incoming payments",
            "maxLength": 64
          },
          "expiresInSeconds": {
            "type": "object",
            "description": "Lifetime of the intent in seconds; defaults to the payment provider's configured lifetime, else one hour",
            "minimum": 60,
            "maximum": 86400
          },
          "clientReference": {
            "type": "string",
            "description": "Your own reference; stored and returned verbatim, never interpreted; unique within your account"
          }
        },
        "required": [
          "walletUid",
          "amountMinor",
          "currency",
          "railCode",
          "clientReference"
        ]
      },
      "TenantTopUpIntentDto": {
        "type": "object",
        "properties": {
          "uid": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "description": "Operation type, e.g. `wallet_credit`, `wallet_debit`, `payout_b2c` or `topup_c2b`"
          },
          "state": {
            "type": "string",
            "description": "Operation state: `created`, `awaiting_authorization`, `authorized`, `held`, `processing`, `pending_provider`, `confirmed`, `failed`, `reversed` or `completed`"
          },
          "amountMinor": {
            "type": "number",
            "description": "Integer minor units (e.g. 250000 = ETB 2,500.00)"
          },
          "feeMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "taxMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "currency": {
            "type": "string",
            "description": "ISO-4217"
          },
          "clientReference": {
            "type": "string",
            "nullable": true,
            "description": "Your reference, exactly as you supplied it"
          },
          "createdAt": {
            "type": "string"
          },
          "completedAt": {
            "type": "string",
            "nullable": true,
            "description": "When the operation first reached a final state"
          },
          "links": {
            "$ref": "#/components/schemas/TenantOperationLinksDto"
          },
          "intentReference": {
            "type": "string",
            "description": "The reference the payer quotes to the provider; 12 digits",
            "example": "048213775902"
          },
          "expiresAt": {
            "type": "string",
            "description": "After this instant a payment against the reference is not matched"
          },
          "railCode": {
            "type": "string",
            "description": "The payment provider's code the intent was issued on"
          },
          "payerInstructions": {
            "type": "string",
            "nullable": true,
            "description": "What to tell the payer, verbatim from the payment provider's configuration; `null` when there is none"
          }
        },
        "required": [
          "uid",
          "type",
          "state",
          "amountMinor",
          "feeMinor",
          "taxMinor",
          "currency",
          "createdAt",
          "links",
          "intentReference",
          "expiresAt",
          "railCode"
        ]
      },
      "TenantOperationTimelineEventDto": {
        "type": "object",
        "properties": {
          "sequenceNo": {
            "type": "number",
            "description": "0 for the creation event, then monotonically increasing"
          },
          "fromState": {
            "type": "string",
            "nullable": true,
            "description": "State the operation moved from; `null` on the creation event"
          },
          "toState": {
            "type": "string",
            "nullable": true,
            "description": "State the operation moved to"
          },
          "occurredAt": {
            "type": "string"
          },
          "actorType": {
            "type": "string",
            "nullable": true,
            "enum": [
              "api_client",
              "admin",
              "system",
              "provider",
              "customer"
            ],
            "description": "Kind of actor that drove the transition; the actor's identity is never included"
          }
        },
        "required": [
          "sequenceNo",
          "occurredAt"
        ]
      },
      "TenantOperationProviderDto": {
        "type": "object",
        "properties": {
          "state": {
            "type": "string",
            "description": "Status at the payment provider: `created`, `initiated`, `pending`, `confirmed`, `failed`, `reversed`, `uncertain` or `reconciled`"
          },
          "reference": {
            "type": "string",
            "nullable": true,
            "description": "The provider's own reference, when known"
          },
          "lastUpdatedAt": {
            "type": "string",
            "description": "Last provider-side change Neo Wallet recorded"
          }
        },
        "required": [
          "state",
          "lastUpdatedAt"
        ]
      },
      "TenantTopUpIntentDetailDto": {
        "type": "object",
        "properties": {
          "uid": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "description": "Operation type, e.g. `wallet_credit`, `wallet_debit`, `payout_b2c` or `topup_c2b`"
          },
          "state": {
            "type": "string",
            "description": "Operation state: `created`, `awaiting_authorization`, `authorized`, `held`, `processing`, `pending_provider`, `confirmed`, `failed`, `reversed` or `completed`"
          },
          "amountMinor": {
            "type": "number",
            "description": "Integer minor units (e.g. 250000 = ETB 2,500.00)"
          },
          "feeMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "taxMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "currency": {
            "type": "string",
            "description": "ISO-4217"
          },
          "clientReference": {
            "type": "string",
            "nullable": true,
            "description": "Your reference, exactly as you supplied it"
          },
          "createdAt": {
            "type": "string"
          },
          "completedAt": {
            "type": "string",
            "nullable": true,
            "description": "When the operation first reached a final state"
          },
          "links": {
            "$ref": "#/components/schemas/TenantOperationLinksDto"
          },
          "timeline": {
            "description": "State transitions of the operation, in `sequenceNo` order",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantOperationTimelineEventDto"
            }
          },
          "provider": {
            "nullable": true,
            "description": "Payment provider status of a top-up or payout; `null` for operations that involve no payment provider",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/TenantOperationProviderDto"
              }
            ]
          },
          "intentReference": {
            "type": "string",
            "description": "The reference the payer quotes to the provider; 12 digits"
          },
          "expiresAt": {
            "type": "string",
            "description": "After this instant a payment against the reference is not matched"
          }
        },
        "required": [
          "uid",
          "type",
          "state",
          "amountMinor",
          "feeMinor",
          "taxMinor",
          "currency",
          "createdAt",
          "links",
          "timeline",
          "intentReference",
          "expiresAt"
        ]
      },
      "TenantOperationDetailDto": {
        "type": "object",
        "properties": {
          "uid": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "description": "Operation type, e.g. `wallet_credit`, `wallet_debit`, `payout_b2c` or `topup_c2b`"
          },
          "state": {
            "type": "string",
            "description": "Operation state: `created`, `awaiting_authorization`, `authorized`, `held`, `processing`, `pending_provider`, `confirmed`, `failed`, `reversed` or `completed`"
          },
          "amountMinor": {
            "type": "number",
            "description": "Integer minor units (e.g. 250000 = ETB 2,500.00)"
          },
          "feeMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "taxMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "currency": {
            "type": "string",
            "description": "ISO-4217"
          },
          "clientReference": {
            "type": "string",
            "nullable": true,
            "description": "Your reference, exactly as you supplied it"
          },
          "createdAt": {
            "type": "string"
          },
          "completedAt": {
            "type": "string",
            "nullable": true,
            "description": "When the operation first reached a final state"
          },
          "links": {
            "$ref": "#/components/schemas/TenantOperationLinksDto"
          },
          "timeline": {
            "description": "State transitions of the operation, in `sequenceNo` order",
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantOperationTimelineEventDto"
            }
          },
          "provider": {
            "nullable": true,
            "description": "Payment provider status of a top-up or payout; `null` for operations that involve no payment provider",
            "type": "object",
            "allOf": [
              {
                "$ref": "#/components/schemas/TenantOperationProviderDto"
              }
            ]
          }
        },
        "required": [
          "uid",
          "type",
          "state",
          "amountMinor",
          "feeMinor",
          "taxMinor",
          "currency",
          "createdAt",
          "links",
          "timeline"
        ]
      },
      "TenantReceiptCounterpartyDto": {
        "type": "object",
        "properties": {
          "hint": {
            "type": "string",
            "nullable": true,
            "description": "Masked counterparty; never the raw value"
          }
        }
      },
      "TenantReceiptReferencesDto": {
        "type": "object",
        "properties": {
          "clientReference": {
            "type": "string",
            "nullable": true,
            "description": "Your reference, exactly as you supplied it"
          },
          "providerReference": {
            "type": "string",
            "nullable": true,
            "description": "The provider's own reference, when known"
          },
          "journalUids": {
            "description": "References of the accounting entries the receipt is computed from",
            "type": "array",
            "items": {
              "type": "string"
            }
          }
        },
        "required": [
          "journalUids"
        ]
      },
      "TenantReceiptFeeDto": {
        "type": "object",
        "properties": {
          "label": {
            "type": "string"
          },
          "amountMinor": {
            "type": "number",
            "description": "Minor units"
          }
        },
        "required": [
          "label",
          "amountMinor"
        ]
      },
      "TenantOperationReceiptDto": {
        "type": "object",
        "properties": {
          "operationUid": {
            "type": "string"
          },
          "type": {
            "type": "string",
            "description": "Operation type, e.g. `wallet_credit`, `wallet_debit`, `payout_b2c` or `topup_c2b`"
          },
          "occurredAt": {
            "type": "string",
            "description": "When the operation completed, otherwise when its money movement was first recorded"
          },
          "amountMinor": {
            "type": "number",
            "description": "Integer minor units (e.g. 250000 = ETB 2,500.00)"
          },
          "feeMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "taxMinor": {
            "type": "number",
            "description": "Minor units"
          },
          "totalDebitedMinor": {
            "type": "number",
            "description": "`amountMinor + feeMinor + taxMinor`, minor units"
          },
          "currency": {
            "type": "string",
            "description": "ISO-4217"
          },
          "counterparty": {
            "$ref": "#/components/schemas/TenantReceiptCounterpartyDto"
          },
          "references": {
            "$ref": "#/components/schemas/TenantReceiptReferencesDto"
          },
          "feeBreakdown": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/TenantReceiptFeeDto"
            }
          },
          "state": {
            "type": "string",
            "description": "Operation state: `created`, `awaiting_authorization`, `authorized`, `held`, `processing`, `pending_provider`, `confirmed`, `failed`, `reversed` or `completed`"
          },
          "receiptHash": {
            "type": "string",
            "description": "SHA-256 (hex) of the canonical receipt; identical on every read"
          }
        },
        "required": [
          "operationUid",
          "type",
          "occurredAt",
          "amountMinor",
          "feeMinor",
          "taxMinor",
          "totalDebitedMinor",
          "currency",
          "counterparty",
          "references",
          "feeBreakdown",
          "state",
          "receiptHash"
        ]
      },
      "ApiError": {
        "type": "object",
        "description": "The one error body every route returns. `message` is a list only for request validation failures, one entry per rejected field. A 403 never says which scope was missing, and a 404 never says whether the resource exists.",
        "required": [
          "statusCode",
          "message",
          "error"
        ],
        "additionalProperties": false,
        "properties": {
          "statusCode": {
            "type": "integer",
            "description": "The HTTP status, repeated."
          },
          "message": {
            "description": "Static, data-free text. Never quotes anything from the request.",
            "oneOf": [
              {
                "type": "string"
              },
              {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            ]
          },
          "error": {
            "type": "string",
            "description": "Stable code to switch on.",
            "enum": [
              "BadRequest",
              "Unauthorized",
              "Forbidden",
              "NotFound",
              "Conflict",
              "UnprocessableEntity",
              "TooManyRequests",
              "InternalError",
              "ServiceUnavailable",
              "InsufficientAvailableBalance",
              "UnbalancedJournal",
              "CurrencyMismatch",
              "ImmutableJournal",
              "JournalAlreadyReversed",
              "SelfApprovalForbidden",
              "LedgerInvariantViolation",
              "TransientConflict",
              "ConfigurationError",
              "AuthorizationInsufficient",
              "AssertionNotBoundToTransaction",
              "FundingAccountNotConfigured",
              "FundingNotPositioned",
              "MandateNotActive",
              "MandateAmountExceeded",
              "MandateFrequencyExceeded",
              "RailUnavailable",
              "StepUpRequired"
            ]
          }
        }
      }
    },
    "parameters": {
      "RequestIdOnRead": {
        "name": "X-Request-Id",
        "in": "header",
        "required": false,
        "description": "Your correlation id for this request: a ULID or a UUID. Generated by the server when absent on a read; echoed on the response either way.",
        "schema": {
          "type": "string"
        }
      },
      "RequestIdOnWrite": {
        "name": "X-Request-Id",
        "in": "header",
        "required": true,
        "description": "Your correlation id for this request: a ULID or a UUID. Required on every write (400 when absent); echoed on the response.",
        "schema": {
          "type": "string"
        }
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "description": "Unique per logical request, at most 128 characters. Resend the same key with the same body to retry safely; the same key with a different body is a 422.",
        "schema": {
          "type": "string",
          "maxLength": 128
        }
      }
    },
    "headers": {
      "XRequestId": {
        "description": "The request id this response belongs to — yours if you sent one.",
        "schema": {
          "type": "string"
        }
      },
      "IdempotentReplayed": {
        "description": "`true` when this body is the stored response of an earlier, completed request with the same `Idempotency-Key`; `false` when this request was processed now.",
        "schema": {
          "type": "string",
          "enum": [
            "true",
            "false"
          ]
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "A required header is missing or the body failed validation.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "The request could not be authenticated. The reason is never disclosed.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Your API account lacks a scope this route requires. Which one is not disclosed.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "NotFound": {
        "description": "No such resource in your account — indistinguishable from one that belongs to another API account.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "Conflict": {
        "description": "A request with this idempotency key is still being processed, or its stored response is no longer available.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "UnprocessableEntity": {
        "description": "The idempotency key was already used for a different request, or a business rule refused it.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "TooManyRequests": {
        "description": "Rate limit exceeded.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "InternalError": {
        "description": "An unexpected error. Quote `X-Request-Id` when reporting it.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      },
      "ServiceUnavailable": {
        "description": "The API is temporarily unable to process the request, or it collided with a concurrent one; retry with the same idempotency key.",
        "headers": {
          "X-Request-Id": {
            "$ref": "#/components/headers/XRequestId"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ApiError"
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "ApiKey": [],
      "KeyId": [],
      "Timestamp": [],
      "Signature": []
    }
  ]
}
