{
  "openapi": "3.1.0",
  "info": {
    "title": "Billing API",
    "version": "0.1.0",
    "description": "Automate your financial operations. Use the Billing API to retrieve detailed settlement reports, manage invoices, monitor transaction fees, and reconcile payouts efficiently across your merchant accounts."
  },
  "servers": [
    {
      "url": "https://pay.izipay.ao",
      "description": "Production"
    },
    {
      "url": "https://pay-sandbox.izipay.ao",
      "description": "Sandbox"
    }
  ],
  "tags": [
    {
      "name": "Authentication",
      "description": "Register users, verify email addresses, issue tokens, recover access, and read the signed-in user profile."
    },
    {
      "name": "MFA",
      "description": "Add or remove multi-factor authentication for a signed-in user."
    },
    {
      "name": "Merchant Access",
      "description": "Manage which users can access a merchant account."
    },
    {
      "name": "Billing",
      "description": "View merchant subscription, invoice, and usage information."
    },
    {
      "name": "Payments",
      "description": "Create, list, sync, and cancel payment operations."
    },
    {
      "name": "PPR References",
      "description": "Create and manage PPR payment references."
    },
    {
      "name": "Terminal Operations",
      "description": "Open, close, and inspect GPO terminal status."
    },
    {
      "name": "SMS Account",
      "description": "Read the signed-in SMS user and merchant sender configuration."
    },
    {
      "name": "SMS Balance",
      "description": "View SMS balance and balance ledger history for the merchant account."
    },
    {
      "name": "SMS Templates",
      "description": "Create and manage reusable SMS message templates."
    },
    {
      "name": "SMS Contacts",
      "description": "Manage SMS contacts and contact lists for bulk sends."
    },
    {
      "name": "SMS Sending",
      "description": "Send SMS messages and inspect sent message history."
    },
    {
      "name": "Scheduled SMS",
      "description": "Schedule SMS messages and list pending or historical scheduled sends."
    }
  ],
  "paths": {
    "/api/merchant/subscription": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get my subscription",
        "description": "Method and route: `GET /api/merchant/subscription`. Returns the subscription attached to the signed-in merchant. Use it to show the merchant's current plan, billing status, and subscription details.",
        "operationId": "getMySubscription",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Merchant subscription.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TodoResponse"
                },
                "example": {
                  "message": "To Be Done Soon"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/merchant/usage/current": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get my usage (current)",
        "description": "Method and route: `GET /api/merchant/usage/current`. Returns the signed-in merchant's current billing-period usage. Use it when a merchant needs a live view of consumption before the next invoice is generated.",
        "operationId": "getMyCurrentUsage",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Current merchant usage.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TodoResponse"
                },
                "example": {
                  "message": "To Be Done Soon"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/merchant/usage/history": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get my usage history",
        "description": "Method and route: `GET /api/merchant/usage/history`. Returns historical usage for the signed-in merchant. Use it for billing dashboards, usage trends, and month-by-month review.",
        "operationId": "getMyUsageHistory",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Merchant usage history.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TodoResponse"
                },
                "example": {
                  "message": "To Be Done Soon"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/merchant/invoices": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get my invoices",
        "description": "Method and route: `GET /api/merchant/invoices`. Returns the invoices for the signed-in merchant. This is the list view a merchant can use to review billing history before opening a specific invoice.",
        "operationId": "getMyInvoices",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "responses": {
          "200": {
            "description": "Merchant invoices.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TodoResponse"
                },
                "example": {
                  "message": "To Be Done Soon"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/merchant/invoices/{invoiceId}": {
      "get": {
        "tags": [
          "Billing"
        ],
        "summary": "Get my invoice details",
        "description": "Method and route: `GET /api/merchant/invoices/{invoiceId}`. Retrieves the details for one invoice that belongs to the signed-in merchant. Use this when a merchant opens an invoice from a list and needs the full billing breakdown.",
        "operationId": "getMyInvoiceDetails",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoiceId"
          }
        ],
        "responses": {
          "200": {
            "description": "Invoice details.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TodoResponse"
                },
                "example": {
                  "message": "To Be Done Soon"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    }
  },
  "webhooks": {
    "pprReferencePaymentNotification": {
      "post": {
        "summary": "PPR reference payment notification",
        "description": "**Merchant Callback Endpoint**\n\nThe callback endpoint is an HTTPS URL hosted by the merchant and provided to the IZI Pay development team during setup. This is the endpoint where IZI Pay sends payment status updates and notifications.\n\nAlong with the callback URL, the merchant must also provide an Access-Key. IZI Pay includes this key in the request headers of every callback request so that the merchant can authenticate and validate incoming notifications.\n\n> The merchant is responsible for ensuring that the callback endpoint is publicly accessible and capable of receiving and processing requests from IZI Pay.\n\nThis callback applies to PPR references created through the current API.\n\n> **Summary**\n>\n> During onboarding, the merchant must provide the following details to the IZI Pay development team:\n>\n> - **Callback URL:** The HTTPS endpoint where IZI Pay will send payment status notifications.\n> - **Access-Key:** A secret value chosen and provided by the merchant. IZI Pay includes this value in the request headers of every callback request, allowing the merchant to verify that the notification originated from IZI Pay.\n",
        "operationId": "receivePprReferencePaymentNotification",
        "parameters": [
          {
            "name": "Access-Key",
            "in": "header",
            "required": true,
            "description": "Access key chosen or generated by the merchant for this webhook. IZI Pay sends this same value in the Access-Key header so your endpoint can authenticate the notification.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MerchantPprWebhookRequest"
              },
              "example": {
                "idTransacao": "00000",
                "numLogSistema": "12967628",
                "idLogSistema": "8588",
                "dataTransaccaoCliente": "2026-06-08T11:52:56",
                "montantePago": 20,
                "tipoTerminal": "M",
                "iIdentTerminal": "0000000000",
                "localidadeTerminal": "Internet ",
                "refPagamento": "744757420",
                "nib": null,
                "banco": null,
                "Id": "f6701cf7-7fb8-4321-b4a1-eb5138ec9f88"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return HTTP 2xx with `Success: true` when the notification was processed successfully or was already processed before.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantWebhookResponse"
                },
                "examples": {
                  "processed": {
                    "summary": "Payment processed",
                    "value": {
                      "Success": true,
                      "Obs": "Payment processed successfully",
                      "Id": "merchant-payment-123"
                    }
                  },
                  "duplicate": {
                    "summary": "Payment already processed",
                    "value": {
                      "Success": true,
                      "Obs": "Payment already processed",
                      "Id": "merchant-payment-123"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "qrCodePaymentNotification": {
      "post": {
        "summary": "QR Code payment notification",
        "description": "**Merchant Callback Endpoint**\n\nThe callback endpoint is an HTTPS URL hosted by the merchant and provided to the IZI Pay development team during setup. This is the endpoint where IZI Pay sends payment status updates and notifications.\n\nAlong with the callback URL, the merchant must also provide an Access-Key. IZI Pay includes this key in the request headers of every callback request so that the merchant can authenticate and validate incoming notifications.\n\n> The merchant is responsible for ensuring that the callback endpoint is publicly accessible and capable of receiving and processing requests from IZI Pay.\n\nThis callback applies to GPO QR Code payments created through the Payments API.\n\n> **Summary**\n>\n> During onboarding, the merchant must provide the following details to the IZI Pay development team:\n>\n> - **Callback URL:** The HTTPS endpoint where IZI Pay will send payment status notifications.\n> - **Access-Key:** A secret value chosen and provided by the merchant. IZI Pay includes this value in the request headers of every callback request, allowing the merchant to verify that the notification originated from IZI Pay.\n",
        "operationId": "receiveQrCodePaymentNotification",
        "parameters": [
          {
            "name": "Access-Key",
            "in": "header",
            "required": true,
            "description": "Access key chosen or generated by the merchant for this webhook. IZI Pay sends this same value in the Access-Key header so your endpoint can authenticate the notification.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/MerchantQrCodeWebhookRequest"
              },
              "example": {
                "creationDate": "2026-06-08T17:26:45.453+01:00",
                "updatedDate": "2026-06-08T17:26:46.269+01:00",
                "id": "5CJ2IZ48T7MAPH1G",
                "amount": 1,
                "clearingPeriod": "4",
                "transactionNumber": "15",
                "status": "ACCEPTED",
                "transactionType": "PAYMENT",
                "orderOrigin": "QR_CODE",
                "currency": "AOA",
                "reference": {
                  "id": "TK050B02NWY9EKU"
                },
                "pointOfSale": {
                  "id": "540128"
                },
                "merchantReferenceNumber": "TK050B02NWY9EKU"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Return HTTP 2xx with `Success: true` when the notification was processed successfully or was already processed before.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantWebhookResponse"
                },
                "examples": {
                  "processed": {
                    "summary": "Payment processed",
                    "value": {
                      "Success": true,
                      "Obs": "Payment processed successfully",
                      "Id": "merchant-payment-123"
                    }
                  },
                  "duplicate": {
                    "summary": "Payment already processed",
                    "value": {
                      "Success": true,
                      "Obs": "Payment already processed",
                      "Id": "merchant-payment-123"
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      },
      "ApiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key"
      }
    },
    "parameters": {
      "MerchantId": {
        "name": "merchantId",
        "in": "path",
        "required": true,
        "description": "Merchant identifier.",
        "schema": {
          "type": "string"
        },
        "example": "BB1376D9-03D3-45C6-82FA-61F4270D27B6"
      },
      "UserId": {
        "name": "userId",
        "in": "path",
        "required": true,
        "description": "User identifier.",
        "schema": {
          "type": "string"
        },
        "example": "11111111-1111-1111-1111-111111111111"
      },
      "InvoiceId": {
        "name": "invoiceId",
        "in": "path",
        "required": true,
        "description": "Invoice identifier.",
        "schema": {
          "type": "string"
        },
        "example": "inv_12345"
      },
      "PaymentId": {
        "name": "paymentId",
        "in": "path",
        "required": true,
        "description": "External payment identifier.",
        "schema": {
          "type": "string"
        },
        "example": "pay_12345"
      },
      "InternalPaymentId": {
        "name": "internalPaymentId",
        "in": "path",
        "required": true,
        "description": "Internal payment GUID.",
        "schema": {
          "type": "string",
          "format": "uuid"
        },
        "example": "a18aa875-7a13-47d3-96ca-795ce9ffafa9"
      },
      "PprReference": {
        "name": "pprReference",
        "in": "path",
        "required": true,
        "description": "PPR reference value.",
        "schema": {
          "type": "string"
        },
        "example": "425882116"
      },
      "PosId": {
        "name": "posId",
        "in": "path",
        "required": true,
        "description": "GPO POS terminal identifier.",
        "schema": {
          "type": "string"
        },
        "example": "413205"
      },
      "SupervisorId": {
        "name": "supervisorId",
        "in": "query",
        "required": false,
        "description": "Optional supervisor identifier for terminal operations.",
        "schema": {
          "type": "string"
        },
        "example": "12345"
      },
      "Page": {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "Page number.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 1
        }
      },
      "PageSize": {
        "name": "pageSize",
        "in": "query",
        "required": false,
        "description": "Number of records per page.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 20
        }
      },
      "PageNumber": {
        "name": "pageNumber",
        "in": "query",
        "required": false,
        "description": "Page number.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "default": 1
        }
      },
      "SmsTemplateId": {
        "name": "templateId",
        "in": "path",
        "required": true,
        "description": "SMS template identifier.",
        "schema": {
          "type": "integer"
        },
        "example": 42
      },
      "SmsContactId": {
        "name": "contactoId",
        "in": "path",
        "required": true,
        "description": "SMS contact identifier.",
        "schema": {
          "type": "integer"
        },
        "example": 120
      },
      "SmsContactListId": {
        "name": "listaId",
        "in": "path",
        "required": true,
        "description": "SMS contact list identifier.",
        "schema": {
          "type": "integer"
        },
        "example": 30
      },
      "Day": {
        "name": "dia",
        "in": "query",
        "required": true,
        "description": "Day of month.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 31
        },
        "example": 14
      },
      "Month": {
        "name": "mes",
        "in": "query",
        "required": true,
        "description": "Month number.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 12
        },
        "example": 6
      },
      "Year": {
        "name": "ano",
        "in": "query",
        "required": true,
        "description": "Four-digit year.",
        "schema": {
          "type": "integer",
          "minimum": 2000
        },
        "example": 2026
      },
      "StartDay": {
        "name": "diaInicio",
        "in": "query",
        "required": true,
        "description": "Start day of month.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 31
        },
        "example": 1
      },
      "StartMonth": {
        "name": "mesInicio",
        "in": "query",
        "required": true,
        "description": "Start month number.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 12
        },
        "example": 6
      },
      "StartYear": {
        "name": "anoInicio",
        "in": "query",
        "required": true,
        "description": "Start year.",
        "schema": {
          "type": "integer",
          "minimum": 2000
        },
        "example": 2026
      },
      "EndDay": {
        "name": "diaFim",
        "in": "query",
        "required": true,
        "description": "End day of month.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 31
        },
        "example": 14
      },
      "EndMonth": {
        "name": "mesFim",
        "in": "query",
        "required": true,
        "description": "End month number.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 12
        },
        "example": 6
      },
      "EndYear": {
        "name": "anoFim",
        "in": "query",
        "required": true,
        "description": "End year.",
        "schema": {
          "type": "integer",
          "minimum": 2000
        },
        "example": 2026
      }
    },
    "schemas": {
      "ClientCredentialsTokenRequest": {
        "type": "object",
        "required": [
          "grant_type",
          "client_id",
          "client_secret",
          "scope"
        ],
        "properties": {
          "grant_type": {
            "type": "string",
            "enum": [
              "client_credentials"
            ]
          },
          "client_id": {
            "type": "string"
          },
          "client_secret": {
            "type": "string",
            "format": "password"
          },
          "scope": {
            "type": "string"
          }
        }
      },
      "PasswordTokenRequest": {
        "type": "object",
        "required": [
          "grant_type",
          "username",
          "password",
          "scope",
          "client_id"
        ],
        "properties": {
          "grant_type": {
            "type": "string",
            "enum": [
              "password"
            ]
          },
          "username": {
            "type": "string",
            "format": "email"
          },
          "password": {
            "type": "string",
            "format": "password"
          },
          "scope": {
            "type": "string"
          },
          "client_id": {
            "type": "string"
          }
        }
      },
      "TokenResponse": {
        "type": "object",
        "properties": {
          "access_token": {
            "type": "string"
          },
          "refresh_token": {
            "type": "string"
          },
          "expires_in": {
            "type": "integer"
          },
          "token_type": {
            "type": "string",
            "example": "Bearer"
          }
        }
      },
      "RegisterUserRequest": {
        "type": "object",
        "required": [
          "email",
          "password",
          "firstName",
          "lastName"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "password": {
            "type": "string",
            "format": "password"
          },
          "firstName": {
            "type": "string"
          },
          "lastName": {
            "type": "string"
          },
          "phoneNumber": {
            "type": "string"
          }
        }
      },
      "TokenOnlyRequest": {
        "type": "object",
        "required": [
          "token"
        ],
        "properties": {
          "token": {
            "type": "string"
          }
        }
      },
      "ForgotPasswordRequest": {
        "type": "object",
        "required": [
          "email"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          }
        }
      },
      "ResetPasswordRequest": {
        "type": "object",
        "required": [
          "token",
          "newPassword"
        ],
        "properties": {
          "token": {
            "type": "string"
          },
          "newPassword": {
            "type": "string",
            "format": "password"
          }
        }
      },
      "UserInfoResponse": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "sub": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "EnableMfaRequest": {
        "type": "object",
        "required": [
          "method"
        ],
        "properties": {
          "method": {
            "type": "integer",
            "description": "MFA method identifier."
          }
        }
      },
      "AddMerchantUserRequest": {
        "type": "object",
        "required": [
          "email",
          "roleId"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email"
          },
          "roleId": {
            "type": "string"
          }
        }
      },
      "CustomMetadata": {
        "type": "object",
        "additionalProperties": true,
        "description": "A merchant-defined JSON object for linking an IZI Pay payment to records in your own systems.\n\nProperty names are chosen by the merchant; the example keys are illustrative and are not a fixed list. Each property may contain a JSON string, number, boolean, array, nested object, or `null`. Key spelling and casing are preserved.\n\nIZI Pay stores these values without using them to control payment processing. They are returned as `customMetadata` by payment creation/detail/list and PPR creation/detail/list responses.\n\nUse this object for internal identifiers such as invoice numbers, purchase orders, departments, customer codes, or source-system references. Do not include passwords, access tokens, card details, or other secrets.",
        "example": {
          "invoiceNumber": "INV-2026-0042",
          "department": "SALES",
          "sourceSystem": "ERP"
        }
      },
      "CreatePaymentRequest": {
        "type": "object",
        "required": [
          "amount",
          "currency",
          "paymentType"
        ],
        "additionalProperties": true,
        "properties": {
          "amount": {
            "type": "number",
            "minimum": 0,
            "maximum": 10000000,
            "description": "Payment amount expressed in the selected currency. Decimals are supported.\n\nFor `GPO` and `PPR` with `metadata.referenceType: Dynamic`, the amount must be between `0.01` and `10,000,000`. For a `PPR` charging reference, use `0` for an open amount that the customer enters when paying; a positive amount is also accepted. Negative values are never allowed."
          },
          "currency": {
            "type": "string",
            "minLength": 3,
            "maxLength": 3,
            "pattern": "^[A-Z]{3}$",
            "description": "Three-letter uppercase ISO-style currency code. Use `AOA` for kwanza payments.",
            "example": "AOA"
          },
          "paymentType": {
            "type": "string",
            "description": "Payment rail to use. `GPO` creates a mobile money, authorization, or QR Code payment; `PPR` creates a payment reference.",
            "enum": [
              "GPO",
              "PPR"
            ]
          },
          "reference": {
            "type": "string",
            "maxLength": 15,
            "description": "Merchant payment identifier. It is required for `GPO` and may contain up to 15 characters (individual GPO methods can impose a stricter format).\n\nFor `PPR`, omit it or send an empty string to have IZI Pay generate a 9-digit reference. To define the reference yourself, send only digits and use between 9 and 15 digits. A merchant-defined dynamic reference cannot be reused while the same reference is active and unpaid for the entity."
          },
          "description": {
            "type": "string",
            "deprecated": true,
            "description": "Legacy top-level description. Connector-specific descriptions are read from `metadata.description`; use that field for new integrations."
          },
          "metadata": {
            "description": "Payment-type-specific settings for `POST /api/payments`.\n\nConnector settings such as `paymentMethod`, `referenceType`, `expiryDate`, and customer fields belong directly in this object. Merchant-defined fields must be grouped inside `metadata.custom`; do not place arbitrary merchant keys alongside connector settings.\n\nValues sent in `metadata.custom` are stored with the payment and returned as the top-level `customMetadata` property in creation and lookup responses. Do not send a top-level `customMetadata` field to `/api/payments`.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/GpoPaymentMetadata"
              },
              {
                "$ref": "#/components/schemas/PprPaymentMetadata"
              }
            ]
          }
        }
      },
      "GpoPaymentMetadata": {
        "type": "object",
        "additionalProperties": true,
        "description": "Settings used when `paymentType` is `GPO`.",
        "properties": {
          "paymentMethod": {
            "type": "string",
            "description": "GPO flow to start. Use `webframe` for hosted checkout, `onetimepurchase` for an immediate mobile payment, `authorization` to reserve funds, `capture` to complete a previous authorization, or `qrcode` to create a QR Code. Defaults to `webframe` when omitted or unrecognized.",
            "enum": [
              "webframe",
              "onetimepurchase",
              "authorization",
              "capture",
              "qrcode"
            ]
          },
          "phoneNumber": {
            "type": "string",
            "description": "Customer mobile number used by mobile payment and authorization flows.",
            "example": "923000000"
          },
          "provider": {
            "type": "string",
            "description": "Mobile network/payment provider used for the transaction.",
            "example": "UNITEL"
          },
          "gpo_merchant_id": {
            "type": "string",
            "description": "GPO merchant identifier assigned during onboarding. It can also be supplied by the authenticated merchant configuration."
          },
          "gpo_pos_id": {
            "type": "string",
            "description": "GPO point-of-sale identifier assigned during onboarding. It can also be supplied by the authenticated merchant configuration."
          },
          "qrSize": {
            "type": "string",
            "description": "Requested QR Code image size. Used only when `paymentMethod` is `qrcode`; defaults to `MEDIUM`.",
            "example": "MEDIUM"
          },
          "qrType": {
            "type": "string",
            "description": "QR Code behavior. Used only when `paymentMethod` is `qrcode`; defaults to `STATIC`.",
            "example": "STATIC"
          },
          "maxTransactions": {
            "type": "integer",
            "minimum": 1,
            "description": "Maximum number of payments accepted by the QR Code. Used only for QR Code payments and defaults to `1`."
          },
          "endDate": {
            "type": "string",
            "format": "date-time",
            "description": "Optional QR Code expiry in ISO 8601 format. Defaults to 24 hours after creation."
          },
          "authorizationId": {
            "type": "string",
            "description": "Identifier returned by a previous authorization. Required when `paymentMethod` is `capture`."
          },
          "description": {
            "type": "string",
            "description": "Description sent to GPO. For QR Code payments, the top-level `reference` is used when this value is omitted."
          },
          "custom": {
            "type": "object",
            "additionalProperties": true,
            "description": "Optional merchant-defined JSON object for internal reconciliation data.\n\nThe merchant chooses the property names. Values may be strings, numbers, booleans, arrays, nested objects, or `null`. IZI Pay does not use these properties to select or configure the GPO payment method.\n\nThe object is returned as `customMetadata` in payment detail and list responses. Do not include credentials, card details, access tokens, or other secrets.",
            "example": {
              "invoiceNumber": "INV-2026-0042",
              "department": "SALES",
              "sourceSystem": "ERP"
            }
          }
        }
      },
      "PprPaymentMetadata": {
        "type": "object",
        "additionalProperties": true,
        "description": "Settings used when `paymentType` is `PPR`.",
        "properties": {
          "referenceType": {
            "type": "string",
            "description": "PPR reference behavior. `Dynamic` is a fixed-amount reference and requires `amount` greater than zero. `Charging` is reusable and can receive multiple transactions; use `amount: 0` when the payer should choose the amount. Defaults to `Dynamic` when omitted.",
            "default": "Dynamic",
            "enum": [
              "Dynamic",
              "Charging"
            ]
          },
          "expiryDate": {
            "type": "string",
            "format": "date-time",
            "description": "Optional ISO 8601 expiry date. If omitted, a dynamic reference expires one month after creation and a charging reference defaults to the end of 2099."
          },
          "description": {
            "type": "string",
            "description": "Merchant-facing reason or label for the reference."
          },
          "customerEmail": {
            "type": "string",
            "format": "email",
            "description": "Optional customer email stored with the reference and returned in the PPR payment response."
          },
          "customerName": {
            "type": "string",
            "description": "Optional customer name stored with the reference and returned in the PPR payment response."
          },
          "customerTelephone": {
            "type": "string",
            "description": "Optional customer telephone number returned in the PPR payment response."
          },
          "documentNumber": {
            "type": "string",
            "description": "Optional customer identity document number returned in payment details."
          },
          "custom": {
            "type": "object",
            "additionalProperties": true,
            "description": "Optional merchant-defined JSON object for linking the PPR payment to your internal records.\n\nThe merchant chooses the property names. Values may be strings, numbers, booleans, arrays, nested objects, or `null`. These values do not affect the generated entity, reference, amount, expiry, or payment status.\n\nSend this object as `metadata.custom` when using `POST /api/payments`. IZI Pay stores it and returns it as the top-level `customMetadata` property in PPR creation and lookup responses. Do not include credentials, card details, access tokens, or other secrets.",
            "example": {
              "invoiceNumber": "INV-2026-0042",
              "department": "SALES",
              "sourceSystem": "ERP"
            }
          }
        }
      },
      "CreatePprReferenceRequest": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "reference": {
            "type": "string",
            "pattern": "^[0-9]{9,15}$",
            "description": "Optional merchant-defined PPR reference containing 9 to 15 digits. Omit it to generate the reference automatically."
          },
          "referenceType": {
            "type": "string",
            "description": "`Dynamic` creates a fixed-amount reference. `Charging` creates a reusable reference and allows an open amount. Defaults to `Dynamic` when omitted.",
            "default": "Dynamic",
            "enum": [
              "Dynamic",
              "Charging"
            ]
          },
          "amount": {
            "type": "number",
            "description": "Required and greater than zero for `Dynamic`; optional for `Charging`, where `0` represents an open amount."
          },
          "expiryDate": {
            "type": "string",
            "format": "date-time",
            "description": "Optional future expiry in ISO 8601 format."
          },
          "description": {
            "type": "string",
            "description": "Optional merchant-facing reason or label for the reference."
          },
          "customerEmail": {
            "type": "string",
            "format": "email",
            "description": "Optional customer email stored with the reference."
          },
          "customerName": {
            "type": "string",
            "description": "Optional customer full name stored with the reference."
          },
          "customerTelephone": {
            "type": "string",
            "description": "Optional customer telephone number stored with the reference."
          },
          "documentNumber": {
            "type": "string",
            "description": "Optional customer identity document number stored with the reference."
          },
          "customMetadata": {
            "type": "object",
            "additionalProperties": true,
            "description": "Optional merchant-defined JSON object for internal reconciliation and record linking.\n\nThis is the direct PPR endpoint form: send `customMetadata` at the request root for `POST /api/references/ppr`, `/api/references/ppr/legacy`, and each item in `/api/references/ppr/bulk`. Do not wrap it in `metadata` or `custom`.\n\nProperty names are chosen by the merchant. Values may be strings, numbers, booleans, arrays, nested objects, or `null`. The values do not affect PPR processing and are returned unchanged as `customMetadata` in creation, detail, and list responses.\n\nDo not include credentials, card details, access tokens, or other secrets.",
            "example": {
              "invoiceNumber": "INV-2026-0042",
              "department": "SALES",
              "sourceSystem": "ERP",
              "purchaseOrder": "PO-98765",
              "customerCode": "CUS-001"
            }
          }
        }
      },
      "CreateBulkPprReferencesRequest": {
        "type": "object",
        "required": [
          "references"
        ],
        "properties": {
          "references": {
            "type": "array",
            "maxItems": 100,
            "items": {
              "$ref": "#/components/schemas/CreatePprReferenceRequest"
            }
          }
        }
      },
      "PaymentCreationResponse": {
        "type": "object",
        "additionalProperties": true,
        "description": "Payment creation response. The exact fields depend on the payment type and method.",
        "properties": {
          "id": {
            "type": "string",
            "description": "For compact PPR responses, this identifies the PPR reference record. Use `reference`, not this field, to call `GET /api/payments/{paymentId}`."
          },
          "internalId": {
            "type": "string",
            "format": "uuid",
            "description": "Internal payment identifier when included by the selected payment flow."
          },
          "entity": {
            "type": "string"
          },
          "reference": {
            "type": "string",
            "description": "Provider/payment reference. For PPR, use this value to retrieve payment details."
          },
          "amount": {
            "type": "number"
          },
          "currency": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "description": {
            "type": "string"
          },
          "customer": {
            "type": "object",
            "properties": {
              "email": {
                "type": "string",
                "format": "email"
              },
              "name": {
                "type": "string"
              },
              "telephone": {
                "type": "string"
              }
            }
          },
          "customMetadata": {
            "$ref": "#/components/schemas/CustomMetadata"
          }
        }
      },
      "PaymentDetailsResponse": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "id": {
            "type": "string"
          },
          "internalId": {
            "type": "string",
            "format": "uuid"
          },
          "merchantId": {
            "type": "string",
            "format": "uuid"
          },
          "reference": {
            "type": "string"
          },
          "amount": {
            "type": "number"
          },
          "currency": {
            "type": "string"
          },
          "paymentType": {
            "type": "string",
            "enum": [
              "GPO",
              "PPR"
            ]
          },
          "status": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "completedAt": {
            "type": "string",
            "format": "date-time"
          },
          "description": {
            "type": "string"
          },
          "customerEmail": {
            "type": "string",
            "format": "email"
          },
          "customerName": {
            "type": "string"
          },
          "customerTelephone": {
            "type": "string"
          },
          "documentNumber": {
            "type": "string"
          },
          "customMetadata": {
            "$ref": "#/components/schemas/CustomMetadata"
          }
        }
      },
      "PagedPaymentsResponse": {
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PaymentDetailsResponse"
            }
          },
          "pageNumber": {
            "type": "integer"
          },
          "pageSize": {
            "type": "integer"
          },
          "totalPages": {
            "type": "integer"
          },
          "totalItems": {
            "type": "integer"
          }
        }
      },
      "PprReferenceResponse": {
        "type": "object",
        "properties": {
          "reference": {
            "type": "string"
          },
          "amount": {
            "type": "number"
          },
          "status": {
            "type": "string"
          },
          "referenceStatus": {
            "type": "string"
          },
          "entity": {
            "type": "string"
          },
          "expiresAt": {
            "type": "string",
            "format": "date-time"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "description": {
            "type": "string"
          },
          "customerEmail": {
            "type": "string",
            "format": "email"
          },
          "customerName": {
            "type": "string"
          },
          "customerTelephone": {
            "type": "string"
          },
          "documentNumber": {
            "type": "string"
          },
          "customMetadata": {
            "$ref": "#/components/schemas/CustomMetadata"
          }
        }
      },
      "PprReferenceListResponse": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PprReferenceResponse"
            }
          },
          "totalCount": {
            "type": "integer"
          },
          "page": {
            "type": "integer"
          },
          "pageSize": {
            "type": "integer"
          }
        }
      },
      "BulkPprReferenceResponse": {
        "type": "object",
        "properties": {
          "successCount": {
            "type": "integer"
          },
          "errorCount": {
            "type": "integer"
          },
          "references": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/PprReferenceResponse"
            }
          },
          "errors": {
            "type": "array",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        }
      },
      "MerchantPprWebhookRequest": {
        "type": "object",
        "required": [
          "idTransacao",
          "numLogSistema",
          "idLogSistema",
          "dataTransaccaoCliente",
          "montantePago",
          "tipoTerminal",
          "iIdentTerminal",
          "localidadeTerminal",
          "refPagamento",
          "Id"
        ],
        "properties": {
          "idTransacao": {
            "type": "string",
            "description": "Transaction identifier."
          },
          "numLogSistema": {
            "type": "string",
            "description": "System log number associated with the payment notification."
          },
          "idLogSistema": {
            "type": "string",
            "description": "System period/log identifier."
          },
          "dataTransaccaoCliente": {
            "type": "string",
            "format": "date-time",
            "description": "Date and time when the customer payment was registered."
          },
          "montantePago": {
            "type": "number",
            "description": "Amount paid by the customer."
          },
          "tipoTerminal": {
            "type": "string",
            "description": "Terminal type used for the payment."
          },
          "iIdentTerminal": {
            "type": "string",
            "description": "Terminal identifier."
          },
          "localidadeTerminal": {
            "type": "string",
            "description": "Terminal location."
          },
          "refPagamento": {
            "type": "string",
            "description": "Payment reference paid by the customer."
          },
          "nib": {
            "type": "string",
            "nullable": true,
            "description": "Debit account NIB, when available."
          },
          "banco": {
            "type": "string",
            "nullable": true,
            "description": "Bank name, when available."
          },
          "Id": {
            "type": "string",
            "format": "uuid",
            "description": "Unique notification identifier. Use this value for idempotency."
          }
        }
      },
      "MerchantQrCodeWebhookRequest": {
        "type": "object",
        "required": [
          "creationDate",
          "updatedDate",
          "id",
          "amount",
          "clearingPeriod",
          "transactionNumber",
          "status",
          "transactionType",
          "orderOrigin",
          "currency",
          "reference",
          "pointOfSale",
          "merchantReferenceNumber"
        ],
        "properties": {
          "creationDate": {
            "type": "string",
            "format": "date-time",
            "description": "Date and time when the QR Code transaction was created."
          },
          "updatedDate": {
            "type": "string",
            "format": "date-time",
            "description": "Date and time when the QR Code transaction status was updated."
          },
          "id": {
            "type": "string",
            "description": "Unique provider transaction identifier. Use this value for idempotency."
          },
          "amount": {
            "type": "number",
            "description": "Amount paid by the customer."
          },
          "clearingPeriod": {
            "type": "string",
            "description": "Clearing period associated with the transaction."
          },
          "transactionNumber": {
            "type": "string",
            "description": "Provider transaction number."
          },
          "status": {
            "type": "string",
            "description": "QR Code payment status.",
            "example": "ACCEPTED"
          },
          "transactionType": {
            "type": "string",
            "description": "Transaction type.",
            "example": "PAYMENT"
          },
          "orderOrigin": {
            "type": "string",
            "description": "Payment order origin.",
            "example": "QR_CODE"
          },
          "currency": {
            "type": "string",
            "description": "Payment currency.",
            "example": "AOA"
          },
          "reference": {
            "type": "object",
            "required": [
              "id"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "QR Code reference identifier."
              }
            }
          },
          "pointOfSale": {
            "type": "object",
            "required": [
              "id"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "Point of sale identifier."
              }
            }
          },
          "merchantReferenceNumber": {
            "type": "string",
            "description": "Merchant reference number associated with the QR Code payment."
          }
        }
      },
      "MerchantWebhookResponse": {
        "type": "object",
        "required": [
          "Success",
          "Obs",
          "Id"
        ],
        "properties": {
          "Success": {
            "type": "boolean",
            "description": "Return true when the notification was processed successfully or was already processed before."
          },
          "Obs": {
            "type": "string",
            "description": "Short processing note."
          },
          "Id": {
            "type": "string",
            "description": "Merchant internal payment identifier."
          }
        }
      },
      "SmsLoggedUser": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "userId": {
            "type": "string",
            "format": "uuid"
          },
          "merchantId": {
            "type": "string",
            "format": "uuid"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "name": {
            "type": "string"
          }
        }
      },
      "SmsMerchant": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "merchantId": {
            "type": "string",
            "format": "uuid"
          },
          "nome": {
            "type": "string"
          },
          "remetenteSms": {
            "type": "string",
            "description": "Sender name configured for SMS messages."
          }
        }
      },
      "SmsBalance": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "merchantId": {
            "type": "string",
            "format": "uuid"
          },
          "saldoAtual": {
            "type": "integer",
            "description": "Current available SMS units."
          },
          "unidade": {
            "type": "string",
            "example": "sms"
          },
          "atualizadoEm": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SmsBalanceLedgerEntry": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "id": {
            "type": "integer"
          },
          "tipo": {
            "type": "string",
            "description": "Ledger entry type, such as credit or debit."
          },
          "quantidade": {
            "type": "integer"
          },
          "saldoDepois": {
            "type": "integer"
          },
          "descricao": {
            "type": "string"
          },
          "criadoEm": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SmsTemplateRequest": {
        "type": "object",
        "required": [
          "nome",
          "conteudo"
        ],
        "properties": {
          "nome": {
            "type": "string"
          },
          "conteudo": {
            "type": "string"
          }
        }
      },
      "SmsTemplate": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "id": {
            "type": "integer"
          },
          "nome": {
            "type": "string"
          },
          "conteudo": {
            "type": "string"
          },
          "criadoEm": {
            "type": "string",
            "format": "date-time"
          },
          "atualizadoEm": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SmsContactRequest": {
        "type": "object",
        "required": [
          "nome",
          "telefone"
        ],
        "properties": {
          "nome": {
            "type": "string"
          },
          "telefone": {
            "type": "string",
            "description": "Destination phone number in the format accepted by the SMS service."
          }
        }
      },
      "SmsContact": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "contactoId": {
            "type": "integer"
          },
          "nome": {
            "type": "string"
          },
          "telefone": {
            "type": "string"
          }
        }
      },
      "SmsContactListRequest": {
        "type": "object",
        "required": [
          "nome",
          "contactoIds"
        ],
        "properties": {
          "nome": {
            "type": "string"
          },
          "contactoIds": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          }
        }
      },
      "SmsContactList": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "listaDeContactoId": {
            "type": "integer"
          },
          "nome": {
            "type": "string"
          },
          "contactoIds": {
            "type": "array",
            "items": {
              "type": "integer"
            }
          },
          "contactos": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SmsContact"
            }
          },
          "totalContactos": {
            "type": "integer"
          }
        }
      },
      "AddSmsContactToListRequest": {
        "type": "object",
        "required": [
          "contactoId",
          "listaId"
        ],
        "properties": {
          "contactoId": {
            "type": "integer"
          },
          "listaId": {
            "type": "integer"
          }
        }
      },
      "SendSmsTextRequest": {
        "type": "object",
        "required": [
          "numerosDestino",
          "conteudo"
        ],
        "properties": {
          "numerosDestino": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "conteudo": {
            "type": "string"
          }
        }
      },
      "SendSmsTemplateRequest": {
        "type": "object",
        "required": [
          "smsId",
          "numerosDestino"
        ],
        "properties": {
          "smsId": {
            "type": "integer",
            "description": "SMS template identifier."
          },
          "numerosDestino": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "remetente": {
            "type": "string"
          }
        }
      },
      "SendSmsListRequest": {
        "type": "object",
        "required": [
          "listaId",
          "conteudo"
        ],
        "properties": {
          "listaId": {
            "type": "integer"
          },
          "remetente": {
            "type": "string"
          },
          "conteudo": {
            "type": "string"
          }
        }
      },
      "SmsSendResult": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "batchId": {
            "type": "string"
          },
          "totalDestinatarios": {
            "type": "integer"
          },
          "estado": {
            "type": "string"
          }
        }
      },
      "SentSms": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "smsId": {
            "type": "integer"
          },
          "telefone": {
            "type": "string"
          },
          "conteudo": {
            "type": "string"
          },
          "estado": {
            "type": "string"
          },
          "enviadoEm": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "ScheduleSmsTextRequest": {
        "type": "object",
        "required": [
          "numerosDestino",
          "conteudo",
          "dia",
          "mes",
          "ano",
          "hora",
          "minuto"
        ],
        "properties": {
          "numerosDestino": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "conteudo": {
            "type": "string"
          },
          "dia": {
            "type": "integer",
            "minimum": 1,
            "maximum": 31
          },
          "mes": {
            "type": "integer",
            "minimum": 1,
            "maximum": 12
          },
          "ano": {
            "type": "integer"
          },
          "hora": {
            "type": "integer",
            "minimum": 0,
            "maximum": 23
          },
          "minuto": {
            "type": "integer",
            "minimum": 0,
            "maximum": 59
          }
        }
      },
      "ScheduledSms": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "agendamentoId": {
            "type": "integer"
          },
          "estado": {
            "type": "string"
          },
          "agendadoPara": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "SmsActionResult": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "success": {
            "type": "boolean"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "SmsContactPage": {
        "type": "object",
        "properties": {
          "pageNumber": {
            "type": "integer"
          },
          "pageSize": {
            "type": "integer"
          },
          "totalCount": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SmsContact"
            }
          }
        }
      },
      "SmsContactListPage": {
        "type": "object",
        "properties": {
          "pageNumber": {
            "type": "integer"
          },
          "pageSize": {
            "type": "integer"
          },
          "totalCount": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SmsContactList"
            }
          }
        }
      },
      "SentSmsPage": {
        "type": "object",
        "properties": {
          "pageNumber": {
            "type": "integer"
          },
          "pageSize": {
            "type": "integer"
          },
          "totalCount": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/SentSms"
            }
          }
        }
      },
      "ScheduledSmsPage": {
        "type": "object",
        "properties": {
          "pageNumber": {
            "type": "integer"
          },
          "pageSize": {
            "type": "integer"
          },
          "totalCount": {
            "type": "integer"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ScheduledSms"
            }
          }
        }
      },
      "SmsPage": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "pageNumber": {
            "type": "integer"
          },
          "pageSize": {
            "type": "integer"
          },
          "totalCount": {
            "type": "integer"
          }
        }
      },
      "TodoResponse": {
        "type": "object",
        "properties": {
          "message": {
            "type": "string",
            "example": "To Be Done Soon"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "message": {
            "type": "string"
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "The request could not be processed.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": "To Be Done Soon",
              "message": "To Be Done Soon"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "The access token is missing, invalid, or expired.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": "To Be Done Soon",
              "message": "To Be Done Soon"
            }
          }
        }
      },
      "NotFound": {
        "description": "The requested resource was not found.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            },
            "example": {
              "code": "To Be Done Soon",
              "message": "To Be Done Soon"
            }
          }
        }
      }
    }
  }
}