{
  "openapi": "3.1.0",
  "info": {
    "title": "API de Pagamentos",
    "version": "0.1.0",
    "description": "O motor central do IZI Pay. Esta API permite processar transações, gerir acessos de comerciantes, gerar referências PPR e interagir diretamente com terminais de pagamento físicos para construir experiências de checkout perfeitas."
  },
  "servers": [
    {
      "url": "https://pay.izipay.ao",
      "description": "Production"
    },
    {
      "url": "https://pay-sandbox.izipay.ao",
      "description": "Sandbox"
    }
  ],
  "tags": [
    {
      "name": "Autenticação",
      "description": "Registar utilizadores, verificar emails, emitir tokens, recuperar acesso e consultar o perfil do utilizador autenticado."
    },
    {
      "name": "MFA",
      "description": "Ativar ou remover autenticação multifator para um utilizador autenticado."
    },
    {
      "name": "Acesso de Comerciante",
      "description": "Gerir quais utilizadores podem aceder a uma conta de comerciante."
    },
    {
      "name": "Faturação",
      "description": "Consultar subscrição, faturas e utilização do comerciante."
    },
    {
      "name": "Pagamentos",
      "description": "Criar, listar, sincronizar e cancelar operações de pagamento."
    },
    {
      "name": "Referências PPR",
      "description": "Criar e gerir referências de pagamento PPR."
    },
    {
      "name": "Operações de Terminal",
      "description": "Abrir, fechar e consultar o estado de terminais GPO."
    },
    {
      "name": "Conta SMS",
      "description": "Consultar o utilizador autenticado e a configuração de remetente SMS do comerciante."
    },
    {
      "name": "Saldo SMS",
      "description": "Consultar o saldo SMS e o histórico de movimentos da conta de comerciante."
    },
    {
      "name": "Templates SMS",
      "description": "Criar e gerir templates reutilizáveis de mensagens SMS."
    },
    {
      "name": "Contactos SMS",
      "description": "Gerir contactos SMS e listas de contactos para envios em massa."
    },
    {
      "name": "Envio SMS",
      "description": "Enviar mensagens SMS e consultar o histórico de mensagens enviadas."
    },
    {
      "name": "SMS Agendado",
      "description": "Agendar mensagens SMS e listar envios agendados."
    }
  ],
  "paths": {
    "/api/merchants/{merchantId}/users": {
      "post": {
        "tags": [
          "Acesso de Comerciante"
        ],
        "summary": "Adicionar utilizador ao comerciante",
        "description": "Método e rota: `POST /api/merchants/{merchantId}/users`. Concede a um utilizador acesso a uma conta de comerciante com o perfil selecionado.",
        "operationId": "addUserToMerchant",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MerchantId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddMerchantUserRequest"
              },
              "example": {
                "email": "simba@partition.ao",
                "roleId": "33333333-3333-3333-3333-333333333333"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "User added to merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TodoResponse"
                },
                "example": {
                  "message": "To Be Done Soon"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/merchants/{merchantId}/users/{userId}": {
      "delete": {
        "tags": [
          "Acesso de Comerciante"
        ],
        "summary": "Remover utilizador do comerciante",
        "description": "Método e rota: `DELETE /api/merchants/{merchantId}/users/{userId}`. Revoga o acesso de um utilizador a uma conta de comerciante.",
        "operationId": "removeUserFromMerchant",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/MerchantId"
          },
          {
            "$ref": "#/components/parameters/UserId"
          }
        ],
        "responses": {
          "200": {
            "description": "User removed from merchant.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TodoResponse"
                },
                "example": {
                  "message": "To Be Done Soon"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/payments": {
      "post": {
        "tags": [
          "Pagamentos"
        ],
        "summary": "Criar pagamento",
        "description": "Método e rota: `POST /api/payments`. Cria um pagamento no gateway. Use o corpo do pedido para escolher o tipo de pagamento, como GPO mobile/QR ou PPR.\n\nTipos de pagamento:\n- `GPO` é usado para fluxos de pagamento mobile money e QR Code. O pedido normalmente inclui metadados específicos de GPO, como método de pagamento, número de telefone ou configurações QR Code, provedor, ID do comerciante e ID do POS.\n- O `PPR` (Pagamento por Referência) é utilizado para fluxos de referências de pagamento. Utilize `referenceType: Dynamic` para referências de montante fixo. Pode deixar o campo `reference` vazio para que a API gere automaticamente a referência, ou indicar o seu próprio número de referência quando o comerciante necessitar de o definir. Utilize `referenceType: Charging` para referências de montante aberto, normalmente com `amount: 0`, permitindo que o montante seja definido no momento do pagamento. As referências do tipo `Charging` podem receber múltiplas transações utilizando a mesma referência.",
        "operationId": "createPayment",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePaymentRequest"
              },
              "examples": {
                "gpoOneTimePurchase": {
                  "summary": "GPO one-time purchase",
                  "value": {
                    "amount": 15,
                    "currency": "AOA",
                    "paymentType": "GPO",
                    "reference": "TEST-1710000000",
                    "description": "GPO mobile payment test",
                    "metadata": {
                      "paymentMethod": "onetimepurchase",
                      "phoneNumber": "923000000",
                      "provider": "UNITEL",
                      "gpo_merchant_id": "185737",
                      "gpo_pos_id": "413205"
                    }
                  }
                },
                "gpoAuthorization": {
                  "summary": "GPO authorization",
                  "value": {
                    "amount": 25,
                    "currency": "AOA",
                    "paymentType": "GPO",
                    "reference": "AUTH-1710000000",
                    "description": "GPO authorization test",
                    "metadata": {
                      "paymentMethod": "authorization",
                      "phoneNumber": "923000000",
                      "provider": "UNITEL",
                      "gpo_merchant_id": "185737",
                      "gpo_pos_id": "413205"
                    }
                  }
                },
                "gpoQrCode": {
                  "summary": "GPO QR code",
                  "value": {
                    "amount": 10,
                    "currency": "AOA",
                    "paymentType": "GPO",
                    "reference": "QR12345",
                    "description": "GPO QR payment test",
                    "metadata": {
                      "paymentMethod": "qrcode",
                      "qrSize": "MEDIUM",
                      "qrType": "STATIC",
                      "maxTransactions": 1,
                      "gpo_merchant_id": "185737",
                      "gpo_pos_id": "413205"
                    }
                  }
                },
                "pprDynamicPayment": {
                  "summary": "Dynamic References",
                  "value": {
                    "paymentType": "PPR",
                    "reference": "",
                    "amount": 1000,
                    "currency": "AOA",
                    "metadata": {
                      "description": "Via Payments API",
                      "referenceType": "Dynamic",
                      "expiryDate": "2026-12-31T23:59:59Z",
                      "customerEmail": "customer@example.com",
                      "customerName": "Jane Doe",
                      "custom": {
                        "invoiceNumber": "INV-2026-0042",
                        "department": "SALES",
                        "sourceSystem": "ERP"
                      }
                    }
                  }
                },
                "pprChargingPayment": {
                  "summary": "Charging References",
                  "value": {
                    "paymentType": "PPR",
                    "reference": "923950476",
                    "amount": 0,
                    "currency": "AOA",
                    "metadata": {
                      "description": "Via Payments API",
                      "referenceType": "Charging",
                      "expiryDate": "2026-12-31T23:59:59Z",
                      "customerEmail": "customer@example.com",
                      "customerName": "Jane Doe",
                      "custom": {
                        "accountNumber": "ACC-2026-0042"
                      }
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Imagem QR Code devolvida na criação de um pagamento QR.",
            "content": {
              "image/png": {
                "schema": {
                  "type": "string",
                  "format": "binary"
                }
              }
            }
          },
          "201": {
            "description": "Pagamento criado. Para PPR, utilize a `reference` devolvida em `GET /api/payments/{paymentId}`.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentCreationResponse"
                },
                "example": {
                  "id": "fb4e17e9-6900-4f68-9f34-984bcd6e5fc9",
                  "entity": "00273",
                  "reference": "584923109",
                  "amount": 1000,
                  "currency": "AOA",
                  "status": "Pending",
                  "createdAt": "2026-09-21T07:59:45.0385627Z",
                  "expiresAt": "2026-12-31T23:59:59Z",
                  "description": "Pagamento de fatura",
                  "customer": {
                    "email": "customer@example.com",
                    "name": "Jane Doe",
                    "telephone": "923950471"
                  },
                  "customMetadata": {
                    "invoiceNumber": "INV-2026-0042",
                    "department": "SALES",
                    "sourceSystem": "ERP"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "get": {
        "tags": [
          "Pagamentos"
        ],
        "summary": "Listar pagamentos",
        "description": "Método e rota: `GET /api/payments`. Devolve uma lista paginada de pagamentos.",
        "operationId": "listPayments",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          }
        ],
        "responses": {
          "200": {
            "description": "Pagamentos paginados.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PagedPaymentsResponse"
                },
                "example": {
                  "data": [
                    {
                      "id": "584923109",
                      "internalId": "8c59c16d-7d56-479d-97d3-c80e3e890a8b",
                      "reference": "584923109",
                      "amount": 1000,
                      "currency": "AOA",
                      "paymentType": "PPR",
                      "status": "Pending",
                      "customMetadata": {
                        "invoiceNumber": "INV-2026-0042",
                        "department": "SALES"
                      }
                    }
                  ],
                  "pageNumber": 1,
                  "pageSize": 20,
                  "totalPages": 1,
                  "totalItems": 1
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/payments/{paymentId}": {
      "get": {
        "tags": [
          "Pagamentos"
        ],
        "summary": "Obter detalhes do pagamento",
        "description": "Método e rota: `GET /api/payments/{paymentId}`. Consulta os detalhes atuais de um pagamento.\n\nPara pagamentos PPR, envie a `reference` devolvida (por exemplo, `584923109`). Também pode utilizar o `internalId` do pagamento quando disponível. O UUID devolvido como `id` na resposta compacta de criação PPR identifica o registo da referência PPR e não é o valor de consulta deste endpoint.",
        "operationId": "getPaymentByExternalId",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PaymentId"
          }
        ],
        "responses": {
          "200": {
            "description": "Detalhes do pagamento.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PaymentDetailsResponse"
                },
                "example": {
                  "id": "584923109",
                  "internalId": "8c59c16d-7d56-479d-97d3-c80e3e890a8b",
                  "merchantId": "ed4fdb07-20bc-4ae4-a5f2-9544d5d9a0cb",
                  "reference": "584923109",
                  "amount": 1000,
                  "currency": "AOA",
                  "paymentType": "PPR",
                  "status": "Pending",
                  "createdAt": "2026-09-21T07:59:45.0385627Z",
                  "description": "Pagamento de fatura",
                  "customerEmail": "customer@example.com",
                  "customerName": "Jane Doe",
                  "customerTelephone": "923950471",
                  "documentNumber": "123456789LA045",
                  "customMetadata": {
                    "invoiceNumber": "INV-2026-0042",
                    "department": "SALES",
                    "sourceSystem": "ERP"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/payments/{paymentId}/sync": {
      "post": {
        "tags": [
          "Pagamentos"
        ],
        "summary": "Sincronizar estado do pagamento",
        "description": "Método e rota: `POST /api/payments/{paymentId}/sync`. Atualiza o estado do pagamento junto do provedor.",
        "operationId": "syncPaymentStatus",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PaymentId"
          }
        ],
        "responses": {
          "200": {
            "description": "Estado do pagamento sincronizado.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TodoResponse"
                },
                "example": {
                  "message": "To Be Done Soon"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/payments/{internalPaymentId}/cancel": {
      "post": {
        "tags": [
          "Pagamentos"
        ],
        "summary": "Cancelar autorização",
        "description": "Método e rota: `POST /api/payments/{internalPaymentId}/cancel`. Cancela uma autorização usando o GUID interno do pagamento.",
        "operationId": "cancelAuthorization",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/InternalPaymentId"
          }
        ],
        "responses": {
          "200": {
            "description": "Autorização cancelada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TodoResponse"
                },
                "example": {
                  "message": "To Be Done Soon"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/references/ppr": {
      "post": {
        "tags": [
          "Referências PPR"
        ],
        "summary": "Criar referência PPR",
        "description": "Método e rota: `POST /api/references/ppr`. Cria uma referência de pagamento PPR. Os valores definidos pelo comerciante em `customMetadata` são guardados com o pagamento e devolvidos pelos endpoints de criação, detalhe e listagem PPR.",
        "operationId": "createPprReference",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePprReferenceRequest"
              },
              "examples": {
                "dynamic": {
                  "summary": "Referência PPR dinâmica",
                  "value": {
                    "reference": "784216539",
                    "referenceType": "Dynamic",
                    "amount": 1500,
                    "expiryDate": "2026-12-31T23:59:59Z",
                    "description": "Pagamento da fatura INV-2026-0042",
                    "customerEmail": "customer@example.com",
                    "customerName": "John Doe",
                    "customerTelephone": "+244923950471",
                    "documentNumber": "123456789LA045",
                    "customMetadata": {
                      "invoiceNumber": "INV-2026-0042",
                      "department": "SALES",
                      "sourceSystem": "ERP",
                      "purchaseOrder": "PO-98765",
                      "customerCode": "CUS-001"
                    }
                  }
                },
                "charging": {
                  "summary": "Referência PPR de carregamento",
                  "value": {
                    "referenceType": "Charging",
                    "amount": 0,
                    "expiryDate": "2026-12-31T23:59:59Z",
                    "description": "Referência reutilizável de carregamento",
                    "customMetadata": {
                      "accountNumber": "ACC-2026-0042"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Referência PPR criada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PprReferenceResponse"
                },
                "example": {
                  "reference": "784216539",
                  "amount": 1500,
                  "status": "Pending",
                  "referenceStatus": "Active",
                  "entity": "00273",
                  "expiresAt": "2026-12-31T23:59:59Z",
                  "createdAt": "2026-09-21T07:59:45.0385627Z",
                  "description": "Pagamento da fatura INV-2026-0042",
                  "customerEmail": "customer@example.com",
                  "customerName": "John Doe",
                  "customerTelephone": "+244923950471",
                  "documentNumber": "123456789LA045",
                  "customMetadata": {
                    "invoiceNumber": "INV-2026-0042",
                    "department": "SALES",
                    "sourceSystem": "ERP",
                    "purchaseOrder": "PO-98765",
                    "customerCode": "CUS-001"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      },
      "get": {
        "tags": [
          "Referências PPR"
        ],
        "summary": "Listar referências PPR",
        "description": "Método e rota: `GET /api/references/ppr`. Devolve uma lista paginada de referências PPR, com filtros opcionais.",
        "operationId": "listPprReferences",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/PageSize"
          },
          {
            "name": "type",
            "in": "query",
            "required": false,
            "description": "Optional PPR reference type filter.",
            "schema": {
              "type": "string",
              "example": "Dynamic"
            }
          },
          {
            "name": "status",
            "in": "query",
            "required": false,
            "description": "Optional PPR reference status filter.",
            "schema": {
              "type": "string",
              "example": "Pending"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Referências PPR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PprReferenceListResponse"
                },
                "example": {
                  "items": [
                    {
                      "reference": "784216539",
                      "amount": 1500,
                      "status": "Pending",
                      "referenceStatus": "Active",
                      "entity": "00273",
                      "expiresAt": "2026-12-31T23:59:59Z",
                      "createdAt": "2026-09-21T07:59:45.0385627Z",
                      "customMetadata": {
                        "invoiceNumber": "INV-2026-0042",
                        "department": "SALES"
                      }
                    }
                  ],
                  "totalCount": 1,
                  "page": 1,
                  "pageSize": 20
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/references/ppr/legacy": {
      "post": {
        "tags": [
          "Referências PPR"
        ],
        "summary": "Criar referência PPR legacy",
        "description": "Método e rota: `POST /api/references/ppr/legacy`. Cria uma referência PPR usando o contrato legacy.",
        "operationId": "createLegacyPprReference",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreatePprReferenceRequest"
              },
              "examples": {
                "dynamic": {
                  "summary": "Referência PPR dinâmica legacy",
                  "value": {
                    "reference": "784216540",
                    "referenceType": "Dynamic",
                    "amount": 1500,
                    "expiryDate": "2026-12-31T23:59:59Z",
                    "description": "Legacy Order #12345",
                    "customerEmail": "customer@example.com",
                    "customerName": "John Doe",
                    "customerTelephone": "923950471",
                    "documentNumber": "123456789LA045",
                    "customMetadata": {
                      "invoiceNumber": "INV-LEGACY-2026-0042"
                    }
                  }
                },
                "charging": {
                  "summary": "Referência PPR de carregamento legacy",
                  "value": {
                    "referenceType": "Charging",
                    "amount": 0,
                    "expiryDate": "2026-12-31T23:59:59Z",
                    "description": "Referência de carregamento legacy reutilizável",
                    "customMetadata": {
                      "accountNumber": "ACC-LEGACY-2026-0042"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Referência PPR legacy criada.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PprReferenceResponse"
                },
                "example": {
                  "reference": "784216540",
                  "amount": 1500,
                  "status": "Pending",
                  "referenceStatus": "Active",
                  "entity": "00273",
                  "expiresAt": "2026-12-31T23:59:59Z",
                  "createdAt": "2026-09-21T07:59:45.0385627Z",
                  "customMetadata": {
                    "invoiceNumber": "INV-LEGACY-2026-0042"
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/references/ppr/bulk": {
      "post": {
        "tags": [
          "Referências PPR"
        ],
        "summary": "Criar referências PPR em lote",
        "description": "Método e rota: `POST /api/references/ppr/bulk`. Cria várias referências PPR num único pedido.",
        "operationId": "createBulkPprReferences",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateBulkPprReferencesRequest"
              },
              "example": {
                "references": [
                  {
                    "referenceType": "Dynamic",
                    "amount": 500,
                    "description": "Item em lote 1",
                    "customerEmail": "a@example.com",
                    "customMetadata": {
                      "invoiceNumber": "INV-BULK-0001"
                    }
                  },
                  {
                    "referenceType": "Dynamic",
                    "amount": 750,
                    "description": "Item em lote 2",
                    "customMetadata": {
                      "invoiceNumber": "INV-BULK-0002"
                    }
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Referências PPR em lote criadas.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BulkPprReferenceResponse"
                },
                "example": {
                  "successCount": 2,
                  "errorCount": 0,
                  "references": [
                    {
                      "reference": "784216541",
                      "amount": 500,
                      "status": "Pending",
                      "entity": "00273",
                      "customMetadata": {
                        "invoiceNumber": "INV-BULK-0001"
                      }
                    },
                    {
                      "reference": "784216542",
                      "amount": 750,
                      "status": "Pending",
                      "entity": "00273",
                      "customMetadata": {
                        "invoiceNumber": "INV-BULK-0002"
                      }
                    }
                  ],
                  "errors": []
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/api/references/ppr/{pprReference}": {
      "get": {
        "tags": [
          "Referências PPR"
        ],
        "summary": "Obter estado da referência PPR",
        "description": "Método e rota: `GET /api/references/ppr/{pprReference}`. Devolve o estado atual de uma referência PPR.",
        "operationId": "getPprReferenceStatus",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PprReference"
          }
        ],
        "responses": {
          "200": {
            "description": "Estado da referência PPR.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/PprReferenceResponse"
                },
                "example": {
                  "reference": "584923109",
                  "amount": 1000,
                  "status": "Pending",
                  "referenceStatus": "Active",
                  "entity": "00273",
                  "expiresAt": "2026-12-31T23:59:59Z",
                  "createdAt": "2026-09-21T07:59:45.0385627Z",
                  "description": "Pagamento de fatura",
                  "customerEmail": "customer@example.com",
                  "customerName": "Jane Doe",
                  "customMetadata": {
                    "invoiceNumber": "INV-2026-0042",
                    "department": "SALES"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      },
      "delete": {
        "tags": [
          "Referências PPR"
        ],
        "summary": "Cancelar referência PPR",
        "description": "Método e rota: `DELETE /api/references/ppr/{pprReference}`. Cancela uma referência PPR existente.",
        "operationId": "cancelPprReference",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PprReference"
          }
        ],
        "responses": {
          "200": {
            "description": "PPR reference canceled.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TodoResponse"
                },
                "example": {
                  "message": "To Be Done Soon"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/references/ppr/{pprReference}/history": {
      "get": {
        "tags": [
          "Referências PPR"
        ],
        "summary": "Obter histórico da referência PPR",
        "description": "Método e rota: `GET /api/references/ppr/{pprReference}/history`. Devolve o histórico de eventos de uma referência PPR.",
        "operationId": "getPprReferenceHistory",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PprReference"
          }
        ],
        "responses": {
          "200": {
            "description": "PPR reference history.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TodoResponse"
                },
                "example": {
                  "message": "To Be Done Soon"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/your-ppr-webhook-path": {
      "post": {
        "tags": [
          "Referências PPR"
        ],
        "summary": "Receber webhook de pagamento PPR",
        "description": "**Endpoint de Callback do Comerciante**\n\nO endpoint de callback é um URL HTTPS hospedado pelo comerciante e fornecido à equipa de desenvolvimento da IZI Pay durante a configuração. Este é o endpoint para onde a IZI Pay envia atualizações de estado do pagamento e notificações.\n\nJuntamente com o URL de callback, o comerciante também deve fornecer um Access-Key. A IZI Pay inclui esta chave nos cabeçalhos de todos os pedidos de callback para que o comerciante possa autenticar e validar as notificações recebidas.\n\n> O comerciante é responsável por garantir que o endpoint de callback está publicamente acessível e é capaz de receber e processar pedidos da IZI Pay.\n\nEste callback aplica-se a referências PPR criadas através da API atual.\n\n> **Resumo**\n>\n> Durante o onboarding, o comerciante deve fornecer os seguintes dados à equipa de desenvolvimento da IZI Pay:\n>\n> - **Callback URL:** O endpoint HTTPS para onde a IZI Pay enviará notificações de estado do pagamento.\n> - **Access-Key:** Um valor secreto escolhido e fornecido pelo comerciante. A IZI Pay inclui este valor nos cabeçalhos de todos os pedidos de callback, permitindo ao comerciante verificar que a notificação teve origem na IZI Pay.\n",
        "operationId": "receivePprPaymentWebhook",
        "servers": [
          {
            "url": "https://seu-dominio.com",
            "description": "Placeholder do host do webhook do comerciante"
          }
        ],
        "parameters": [
          {
            "name": "Access-Key",
            "in": "header",
            "required": true,
            "description": "Chave de acesso escolhida ou gerada pelo comerciante para este webhook. A IZI Pay envia este mesmo valor no cabeçalho Access-Key para que o seu endpoint possa autenticar a notificação.",
            "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": "Devolva HTTP 2xx com `Success: true` quando a notificação for processada com sucesso ou já tiver sido processada antes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantWebhookResponse"
                },
                "examples": {
                  "processed": {
                    "summary": "Pagamento processado",
                    "value": {
                      "Success": true,
                      "Obs": "Pagamento processado com sucesso",
                      "Id": "merchant-payment-123"
                    }
                  },
                  "duplicate": {
                    "summary": "Pagamento já processado",
                    "value": {
                      "Success": true,
                      "Obs": "Pagamento já processado",
                      "Id": "merchant-payment-123"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/your-qr-code-webhook-path": {
      "post": {
        "tags": [
          "Pagamentos"
        ],
        "summary": "Receber webhook de pagamento QR Code",
        "description": "**Endpoint de Callback do Comerciante**\n\nO endpoint de callback é um URL HTTPS hospedado pelo comerciante e fornecido à equipa de desenvolvimento da IZI Pay durante a configuração. Este é o endpoint para onde a IZI Pay envia atualizações de estado do pagamento e notificações.\n\nJuntamente com o URL de callback, o comerciante também deve fornecer um Access-Key. A IZI Pay inclui esta chave nos cabeçalhos de todos os pedidos de callback para que o comerciante possa autenticar e validar as notificações recebidas.\n\n> O comerciante é responsável por garantir que o endpoint de callback está publicamente acessível e é capaz de receber e processar pedidos da IZI Pay.\n\nEste callback aplica-se a pagamentos GPO QR Code criados através da API de Pagamentos.\n\n> **Resumo**\n>\n> Durante o onboarding, o comerciante deve fornecer os seguintes dados à equipa de desenvolvimento da IZI Pay:\n>\n> - **Callback URL:** O endpoint HTTPS para onde a IZI Pay enviará notificações de estado do pagamento.\n> - **Access-Key:** Um valor secreto escolhido e fornecido pelo comerciante. A IZI Pay inclui este valor nos cabeçalhos de todos os pedidos de callback, permitindo ao comerciante verificar que a notificação teve origem na IZI Pay.\n",
        "operationId": "receiveQrCodePaymentWebhook",
        "servers": [
          {
            "url": "https://seu-dominio.com",
            "description": "Placeholder do host do webhook do comerciante"
          }
        ],
        "parameters": [
          {
            "name": "Access-Key",
            "in": "header",
            "required": true,
            "description": "Chave de acesso escolhida ou gerada pelo comerciante para este webhook. A IZI Pay envia este mesmo valor no cabeçalho Access-Key para que o seu endpoint possa autenticar a notificação.",
            "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": "Devolva HTTP 2xx com `Success: true` quando a notificação for processada com sucesso ou já tiver sido processada antes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantWebhookResponse"
                },
                "examples": {
                  "processed": {
                    "summary": "Pagamento processado",
                    "value": {
                      "Success": true,
                      "Obs": "Pagamento processado com sucesso",
                      "Id": "merchant-payment-123"
                    }
                  },
                  "duplicate": {
                    "summary": "Pagamento já processado",
                    "value": {
                      "Success": true,
                      "Obs": "Pagamento já processado",
                      "Id": "merchant-payment-123"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "/api/terminals/{posId}": {
      "get": {
        "tags": [
          "Operações de Terminal"
        ],
        "summary": "Obter estado do terminal",
        "description": "Método e rota: `GET /api/terminals/{posId}`. Devolve o estado atual de um terminal GPO.",
        "operationId": "getTerminalStatus",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PosId"
          }
        ],
        "responses": {
          "200": {
            "description": "Terminal status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TodoResponse"
                },
                "example": {
                  "message": "To Be Done Soon"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/terminals/{posId}/open": {
      "get": {
        "tags": [
          "Operações de Terminal"
        ],
        "summary": "Abrir terminal",
        "description": "Método e rota: `GET /api/terminals/{posId}/open`. Abre um terminal GPO. Inclua `supervisorId` quando for necessaria aprovacao de supervisor.",
        "operationId": "openTerminal",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PosId"
          },
          {
            "$ref": "#/components/parameters/SupervisorId"
          }
        ],
        "responses": {
          "200": {
            "description": "Terminal opened.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/TodoResponse"
                },
                "example": {
                  "message": "To Be Done Soon"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          }
        }
      }
    },
    "/api/terminals/{posId}/close": {
      "get": {
        "tags": [
          "Operações de Terminal"
        ],
        "summary": "Fechar terminal",
        "description": "Método e rota: `GET /api/terminals/{posId}/close`. Fecha um terminal GPO. Inclua `supervisorId` quando for necessaria aprovacao de supervisor.",
        "operationId": "closeTerminal",
        "security": [
          {
            "bearerAuth": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/PosId"
          },
          {
            "$ref": "#/components/parameters/SupervisorId"
          }
        ],
        "responses": {
          "200": {
            "description": "Terminal closed.",
            "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": "Notificação de pagamento de referência PPR",
        "description": "**Endpoint de Callback do Comerciante**\n\nO endpoint de callback é um URL HTTPS hospedado pelo comerciante e fornecido à equipa de desenvolvimento da IZI Pay durante a configuração. Este é o endpoint para onde a IZI Pay envia atualizações de estado do pagamento e notificações.\n\nJuntamente com o URL de callback, o comerciante também deve fornecer um Access-Key. A IZI Pay inclui esta chave nos cabeçalhos de todos os pedidos de callback para que o comerciante possa autenticar e validar as notificações recebidas.\n\n> O comerciante é responsável por garantir que o endpoint de callback está publicamente acessível e é capaz de receber e processar pedidos da IZI Pay.\n\nEste callback aplica-se a referências PPR criadas através da API atual.\n\n> **Resumo**\n>\n> Durante o onboarding, o comerciante deve fornecer os seguintes dados à equipa de desenvolvimento da IZI Pay:\n>\n> - **Callback URL:** O endpoint HTTPS para onde a IZI Pay enviará notificações de estado do pagamento.\n> - **Access-Key:** Um valor secreto escolhido e fornecido pelo comerciante. A IZI Pay inclui este valor nos cabeçalhos de todos os pedidos de callback, permitindo ao comerciante verificar que a notificação teve origem na IZI Pay.\n",
        "operationId": "receivePprReferencePaymentNotification",
        "parameters": [
          {
            "name": "Access-Key",
            "in": "header",
            "required": true,
            "description": "Chave de acesso escolhida ou gerada pelo comerciante para este webhook. A IZI Pay envia este mesmo valor no cabeçalho Access-Key para que o seu endpoint possa autenticar a notificação.",
            "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": "Devolva HTTP 2xx com `Success: true` quando a notificação for processada com sucesso ou já tiver sido processada antes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantWebhookResponse"
                },
                "examples": {
                  "processed": {
                    "summary": "Pagamento processado",
                    "value": {
                      "Success": true,
                      "Obs": "Pagamento processado com sucesso",
                      "Id": "merchant-payment-123"
                    }
                  },
                  "duplicate": {
                    "summary": "Pagamento já processado",
                    "value": {
                      "Success": true,
                      "Obs": "Pagamento já processado",
                      "Id": "merchant-payment-123"
                    }
                  }
                }
              }
            }
          }
        }
      }
    },
    "qrCodePaymentNotification": {
      "post": {
        "summary": "Notificação de pagamento QR Code",
        "description": "**Endpoint de Callback do Comerciante**\n\nO endpoint de callback é um URL HTTPS hospedado pelo comerciante e fornecido à equipa de desenvolvimento da IZI Pay durante a configuração. Este é o endpoint para onde a IZI Pay envia atualizações de estado do pagamento e notificações.\n\nJuntamente com o URL de callback, o comerciante também deve fornecer um Access-Key. A IZI Pay inclui esta chave nos cabeçalhos de todos os pedidos de callback para que o comerciante possa autenticar e validar as notificações recebidas.\n\n> O comerciante é responsável por garantir que o endpoint de callback está publicamente acessível e é capaz de receber e processar pedidos da IZI Pay.\n\nEste callback aplica-se a pagamentos GPO QR Code criados através da API de Pagamentos.\n\n> **Resumo**\n>\n> Durante o onboarding, o comerciante deve fornecer os seguintes dados à equipa de desenvolvimento da IZI Pay:\n>\n> - **Callback URL:** O endpoint HTTPS para onde a IZI Pay enviará notificações de estado do pagamento.\n> - **Access-Key:** Um valor secreto escolhido e fornecido pelo comerciante. A IZI Pay inclui este valor nos cabeçalhos de todos os pedidos de callback, permitindo ao comerciante verificar que a notificação teve origem na IZI Pay.\n",
        "operationId": "receiveQrCodePaymentNotification",
        "parameters": [
          {
            "name": "Access-Key",
            "in": "header",
            "required": true,
            "description": "Chave de acesso escolhida ou gerada pelo comerciante para este webhook. A IZI Pay envia este mesmo valor no cabeçalho Access-Key para que o seu endpoint possa autenticar a notificação.",
            "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": "Devolva HTTP 2xx com `Success: true` quando a notificação for processada com sucesso ou já tiver sido processada antes.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/MerchantWebhookResponse"
                },
                "examples": {
                  "processed": {
                    "summary": "Pagamento processado",
                    "value": {
                      "Success": true,
                      "Obs": "Pagamento processado com sucesso",
                      "Id": "merchant-payment-123"
                    }
                  },
                  "duplicate": {
                    "summary": "Pagamento já processado",
                    "value": {
                      "Success": true,
                      "Obs": "Pagamento já processado",
                      "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": "Objeto JSON definido pelo comerciante para associar um pagamento IZI Pay aos registos dos seus próprios sistemas.\n\nOs nomes das propriedades são escolhidos pelo comerciante; as chaves do exemplo são ilustrativas e não constituem uma lista fixa. Cada propriedade pode conter uma string, número, booleano, array, objeto aninhado ou `null`. A escrita e a capitalização das chaves são preservadas.\n\nA IZI Pay guarda estes valores sem os utilizar para controlar o processamento do pagamento. São devolvidos como `customMetadata` nas respostas de criação, detalhe e listagem de pagamentos e referências PPR.\n\nUtilize este objeto para identificadores internos, como números de fatura, ordens de compra, departamentos, códigos de cliente ou referências do sistema de origem. Não inclua palavras-passe, tokens de acesso, dados de cartão ou outros segredos.",
        "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": "Montante do pagamento expresso na moeda selecionada. São suportados valores decimais.\n\nPara `GPO` e `PPR` com `metadata.referenceType: Dynamic`, o montante deve estar entre `0.01` e `10.000.000`. Numa referência `PPR` do tipo `Charging`, utilize `0` para um montante aberto, introduzido pelo cliente no momento do pagamento; também é aceite um montante positivo. Valores negativos nunca são permitidos."
          },
          "currency": {
            "type": "string",
            "minLength": 3,
            "maxLength": 3,
            "pattern": "^[A-Z]{3}$",
            "description": "Código de moeda de três letras maiúsculas, no formato ISO. Utilize `AOA` para pagamentos em kwanzas.",
            "example": "AOA"
          },
          "paymentType": {
            "type": "string",
            "description": "Meio de pagamento a utilizar. `GPO` cria um pagamento mobile money, uma autorização ou um QR Code; `PPR` cria uma referência de pagamento.",
            "enum": [
              "GPO",
              "PPR"
            ]
          },
          "reference": {
            "type": "string",
            "maxLength": 15,
            "description": "Identificador de pagamento definido pelo comerciante. É obrigatório para `GPO` e pode ter até 15 caracteres (cada método GPO pode impor um formato mais restrito).\n\nPara `PPR`, omita o campo ou envie uma string vazia para que a IZI Pay gere uma referência de 9 dígitos. Para definir a referência, envie apenas dígitos e utilize entre 9 e 15 dígitos. Uma referência dinâmica definida pelo comerciante não pode ser reutilizada enquanto a mesma referência estiver ativa e não paga para a entidade."
          },
          "description": {
            "type": "string",
            "deprecated": true,
            "description": "Descrição de topo legada. As descrições específicas do conector são lidas de `metadata.description`; utilize esse campo em novas integrações."
          },
          "metadata": {
            "description": "Configurações específicas do tipo de pagamento para `POST /api/payments`.\n\nAs configurações do conector, como `paymentMethod`, `referenceType`, `expiryDate` e os campos do cliente, pertencem diretamente a este objeto. Os campos definidos pelo comerciante devem ser agrupados em `metadata.custom`; não coloque chaves arbitrárias do comerciante ao lado das configurações do conector.\n\nOs valores enviados em `metadata.custom` são guardados com o pagamento e devolvidos na propriedade de topo `customMetadata` nas respostas de criação e consulta. Não envie um campo `customMetadata` no topo do pedido para `/api/payments`.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/GpoPaymentMetadata"
              },
              {
                "$ref": "#/components/schemas/PprPaymentMetadata"
              }
            ]
          }
        }
      },
      "GpoPaymentMetadata": {
        "type": "object",
        "additionalProperties": true,
        "description": "Configurações utilizadas quando `paymentType` é `GPO`.",
        "properties": {
          "paymentMethod": {
            "type": "string",
            "description": "Fluxo GPO a iniciar. Utilize `webframe` para checkout alojado, `onetimepurchase` para um pagamento mobile imediato, `authorization` para reservar fundos, `capture` para concluir uma autorização anterior ou `qrcode` para criar um QR Code. Assume `webframe` quando omitido ou não reconhecido.",
            "enum": [
              "webframe",
              "onetimepurchase",
              "authorization",
              "capture",
              "qrcode"
            ]
          },
          "phoneNumber": {
            "type": "string",
            "description": "Número de telemóvel do cliente utilizado nos fluxos de pagamento mobile e autorização.",
            "example": "923000000"
          },
          "provider": {
            "type": "string",
            "description": "Operadora móvel ou provedor de pagamento utilizado na transação.",
            "example": "UNITEL"
          },
          "gpo_merchant_id": {
            "type": "string",
            "description": "Identificador GPO do comerciante atribuído no onboarding. Também pode ser obtido da configuração do comerciante autenticado."
          },
          "gpo_pos_id": {
            "type": "string",
            "description": "Identificador GPO do ponto de venda atribuído no onboarding. Também pode ser obtido da configuração do comerciante autenticado."
          },
          "qrSize": {
            "type": "string",
            "description": "Tamanho solicitado para a imagem do QR Code. Utilizado apenas quando `paymentMethod` é `qrcode`; assume `MEDIUM` quando omitido.",
            "example": "MEDIUM"
          },
          "qrType": {
            "type": "string",
            "description": "Comportamento do QR Code. Utilizado apenas quando `paymentMethod` é `qrcode`; assume `STATIC` quando omitido.",
            "example": "STATIC"
          },
          "maxTransactions": {
            "type": "integer",
            "minimum": 1,
            "description": "Número máximo de pagamentos aceites pelo QR Code. Utilizado apenas em pagamentos por QR Code e assume `1` quando omitido."
          },
          "endDate": {
            "type": "string",
            "format": "date-time",
            "description": "Expiração opcional do QR Code em formato ISO 8601. Assume 24 horas após a criação quando omitida."
          },
          "authorizationId": {
            "type": "string",
            "description": "Identificador devolvido por uma autorização anterior. Obrigatório quando `paymentMethod` é `capture`."
          },
          "description": {
            "type": "string",
            "description": "Descrição enviada ao GPO. Em pagamentos por QR Code, é utilizada a `reference` de topo quando este valor é omitido."
          },
          "custom": {
            "type": "object",
            "additionalProperties": true,
            "description": "Objeto JSON opcional definido pelo comerciante para dados internos de reconciliação.\n\nO comerciante escolhe os nomes das propriedades. Os valores podem ser strings, números, booleanos, arrays, objetos aninhados ou `null`. A IZI Pay não utiliza estas propriedades para selecionar ou configurar o método de pagamento GPO.\n\nO objeto é devolvido como `customMetadata` nas respostas de detalhe e listagem de pagamentos. Não inclua credenciais, dados de cartão, tokens de acesso ou outros segredos.",
            "example": {
              "invoiceNumber": "INV-2026-0042",
              "department": "SALES",
              "sourceSystem": "ERP"
            }
          }
        }
      },
      "PprPaymentMetadata": {
        "type": "object",
        "additionalProperties": true,
        "description": "Configurações utilizadas quando `paymentType` é `PPR`.",
        "properties": {
          "referenceType": {
            "type": "string",
            "description": "Comportamento da referência PPR. `Dynamic` é uma referência de montante fixo e exige `amount` superior a zero. `Charging` é reutilizável e pode receber múltiplas transações; utilize `amount: 0` quando o pagador deve escolher o montante. Assume `Dynamic` quando omitido.",
            "default": "Dynamic",
            "enum": [
              "Dynamic",
              "Charging"
            ]
          },
          "expiryDate": {
            "type": "string",
            "format": "date-time",
            "description": "Data de expiração ISO 8601 opcional. Quando omitida, uma referência dinâmica expira um mês após a criação e uma referência charging assume o final de 2099."
          },
          "description": {
            "type": "string",
            "description": "Motivo ou designação da referência definido pelo comerciante."
          },
          "customerEmail": {
            "type": "string",
            "format": "email",
            "description": "Email opcional do cliente, guardado com a referência e devolvido na resposta do pagamento PPR."
          },
          "customerName": {
            "type": "string",
            "description": "Nome opcional do cliente, guardado com a referência e devolvido na resposta do pagamento PPR."
          },
          "customerTelephone": {
            "type": "string",
            "description": "Número de telefone opcional do cliente, devolvido na resposta do pagamento PPR."
          },
          "documentNumber": {
            "type": "string",
            "description": "Número opcional do documento de identificação do cliente, devolvido nos detalhes do pagamento."
          },
          "custom": {
            "type": "object",
            "additionalProperties": true,
            "description": "Objeto JSON opcional definido pelo comerciante para associar o pagamento PPR aos seus registos internos.\n\nO comerciante escolhe os nomes das propriedades. Os valores podem ser strings, números, booleanos, arrays, objetos aninhados ou `null`. Estes valores não afetam a entidade, referência, montante, expiração ou estado do pagamento.\n\nEnvie este objeto como `metadata.custom` ao utilizar `POST /api/payments`. A IZI Pay guarda-o e devolve-o na propriedade de topo `customMetadata` nas respostas de criação e consulta PPR. Não inclua credenciais, dados de cartão, tokens de acesso ou outros segredos.",
            "example": {
              "invoiceNumber": "INV-2026-0042",
              "department": "SALES",
              "sourceSystem": "ERP"
            }
          }
        }
      },
      "CreatePprReferenceRequest": {
        "type": "object",
        "additionalProperties": true,
        "properties": {
          "reference": {
            "type": "string",
            "pattern": "^[0-9]{9,15}$",
            "description": "Referência PPR opcional, definida pelo comerciante, com 9 a 15 dígitos. Omita para gerar automaticamente."
          },
          "referenceType": {
            "type": "string",
            "description": "`Dynamic` cria uma referência de montante fixo. `Charging` cria uma referência reutilizável e permite montante aberto. Assume `Dynamic` quando omitido.",
            "default": "Dynamic",
            "enum": [
              "Dynamic",
              "Charging"
            ]
          },
          "amount": {
            "type": "number",
            "description": "Obrigatório e superior a zero para `Dynamic`; opcional para `Charging`, onde `0` representa um montante aberto."
          },
          "expiryDate": {
            "type": "string",
            "format": "date-time",
            "description": "Data futura de expiração opcional no formato ISO 8601."
          },
          "description": {
            "type": "string",
            "description": "Motivo ou designação opcional da referência, visível ao comerciante."
          },
          "customerEmail": {
            "type": "string",
            "format": "email",
            "description": "Email opcional do cliente, guardado com a referência."
          },
          "customerName": {
            "type": "string",
            "description": "Nome completo opcional do cliente, guardado com a referência."
          },
          "customerTelephone": {
            "type": "string",
            "description": "Número de telefone opcional do cliente, guardado com a referência."
          },
          "documentNumber": {
            "type": "string",
            "description": "Número opcional do documento de identificação do cliente, guardado com a referência."
          },
          "customMetadata": {
            "type": "object",
            "additionalProperties": true,
            "description": "Objeto JSON opcional definido pelo comerciante para reconciliação interna e associação de registos.\n\nEsta é a forma utilizada pelos endpoints PPR diretos: envie `customMetadata` na raiz do pedido para `POST /api/references/ppr`, `/api/references/ppr/legacy` e em cada item de `/api/references/ppr/bulk`. Não envolva este campo em `metadata` ou `custom`.\n\nOs nomes das propriedades são escolhidos pelo comerciante. Os valores podem ser strings, números, booleanos, arrays, objetos aninhados ou `null`. Os valores não afetam o processamento PPR e são devolvidos sem alteração como `customMetadata` nas respostas de criação, detalhe e listagem.\n\nNão inclua credenciais, dados de cartão, tokens de acesso ou outros segredos.",
            "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": "Resposta de criação do pagamento. Os campos exatos dependem do tipo e método de pagamento.",
        "properties": {
          "id": {
            "type": "string",
            "description": "Nas respostas PPR compactas, identifica o registo da referência PPR. Utilize `reference`, e não este campo, em `GET /api/payments/{paymentId}`."
          },
          "internalId": {
            "type": "string",
            "format": "uuid",
            "description": "Identificador interno do pagamento, quando incluído pelo fluxo selecionado."
          },
          "entity": {
            "type": "string"
          },
          "reference": {
            "type": "string",
            "description": "Referência do provedor/pagamento. Para PPR, utilize este valor para consultar os detalhes."
          },
          "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": "Identificador da transação."
          },
          "numLogSistema": {
            "type": "string",
            "description": "Número de log do sistema associado à notificação de pagamento."
          },
          "idLogSistema": {
            "type": "string",
            "description": "Identificador de período/log do sistema."
          },
          "dataTransaccaoCliente": {
            "type": "string",
            "format": "date-time",
            "description": "Data e hora em que o pagamento do cliente foi registado."
          },
          "montantePago": {
            "type": "number",
            "description": "Montante pago pelo cliente."
          },
          "tipoTerminal": {
            "type": "string",
            "description": "Tipo de terminal usado no pagamento."
          },
          "iIdentTerminal": {
            "type": "string",
            "description": "Identificador do terminal."
          },
          "localidadeTerminal": {
            "type": "string",
            "description": "Localidade do terminal."
          },
          "refPagamento": {
            "type": "string",
            "description": "Referência de pagamento paga pelo cliente."
          },
          "nib": {
            "type": "string",
            "nullable": true,
            "description": "NIB da conta debitada, quando disponível."
          },
          "banco": {
            "type": "string",
            "nullable": true,
            "description": "Nome do banco, quando disponível."
          },
          "Id": {
            "type": "string",
            "format": "uuid",
            "description": "Identificador único da notificação. Use este valor para idempotência."
          }
        }
      },
      "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": "Data e hora em que a transação QR Code foi criada."
          },
          "updatedDate": {
            "type": "string",
            "format": "date-time",
            "description": "Data e hora em que o estado da transação QR Code foi atualizado."
          },
          "id": {
            "type": "string",
            "description": "Identificador único da transação no provedor. Use este valor para idempotência."
          },
          "amount": {
            "type": "number",
            "description": "Montante pago pelo cliente."
          },
          "clearingPeriod": {
            "type": "string",
            "description": "Período de compensação associado à transação."
          },
          "transactionNumber": {
            "type": "string",
            "description": "Número da transação no provedor."
          },
          "status": {
            "type": "string",
            "description": "Estado do pagamento QR Code.",
            "example": "ACCEPTED"
          },
          "transactionType": {
            "type": "string",
            "description": "Tipo da transação.",
            "example": "PAYMENT"
          },
          "orderOrigin": {
            "type": "string",
            "description": "Origem da ordem de pagamento.",
            "example": "QR_CODE"
          },
          "currency": {
            "type": "string",
            "description": "Moeda do pagamento.",
            "example": "AOA"
          },
          "reference": {
            "type": "object",
            "required": [
              "id"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "Identificador da referência QR Code."
              }
            }
          },
          "pointOfSale": {
            "type": "object",
            "required": [
              "id"
            ],
            "properties": {
              "id": {
                "type": "string",
                "description": "Identificador do ponto de venda."
              }
            }
          },
          "merchantReferenceNumber": {
            "type": "string",
            "description": "Número de referência do comerciante associado ao pagamento QR Code."
          }
        }
      },
      "MerchantWebhookResponse": {
        "type": "object",
        "required": [
          "Success",
          "Obs",
          "Id"
        ],
        "properties": {
          "Success": {
            "type": "boolean",
            "description": "Devolva true quando a notificação for processada com sucesso ou já tiver sido processada antes."
          },
          "Obs": {
            "type": "string",
            "description": "Nota curta sobre o processamento."
          },
          "Id": {
            "type": "string",
            "description": "Identificador interno do pagamento no sistema do comerciante."
          }
        }
      },
      "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"
            }
          }
        }
      }
    }
  }
}