{
  "openapi": "3.1.1",
  "info": {
    "title": "PaymentEngine API",
    "description": "API del motor de pagos de Crezcamos: onboarding y KYC de comercios, links de pago y webhooks.\n\n**Autenticación.** Casi todo requiere un JWT de Keycloak (`Authorization: Bearer <token>`).\nUn comercio ya aprobado obtiene el token con *client credentials* (su `client_id` es el UUID del\ncomercio); un comercio que se registró solo inicia sesión con su correo y contraseña (el token trae\n`preferred_username` = id del comercio); el administrador tiene el rol `bank-admin`. El registro\npúblico (`POST /api/onboarding/register`) y los webhooks entrantes no usan token.\n\n**Formato.** Las respuestas siguen JSON:API (`application/vnd.api+json`): `{ data: { type, id,\nattributes } }`. Los errores vienen como `{ errors: [{ status, title, detail, source: { pointer } }] }`;\nun error de validación trae un elemento por campo y `source.pointer` indica cuál\n(`/data/attributes/<ruta>`).\n\n**Versionado.** Cabecera opcional `X-API-VERSION`; sin ella se asume `1.0`.",
    "version": "v1"
  },
  "servers": [
    {
      "url": "https://api.example.com",
      "description": "Producción (reemplazar por el host de tu ambiente)"
    },
    {
      "url": "http://localhost:18083",
      "description": "Local (kind)"
    }
  ],
  "paths": {
    "/api/web-checkouts/subdomain-availability": {
      "get": {
        "tags": [
          "Web checkouts"
        ],
        "summary": "Consultar un subdominio",
        "description": "`name` = subdominio a consultar. Responde `available` y, si no lo está, el motivo (`reason`: formato inválido, reservado o en uso). `checkout_id` (opcional) excluye ese checkout, para que no vea su propio subdominio como ocupado.",
        "operationId": "WebCheckoutsSubdomainAvailability",
        "parameters": [
          {
            "name": "name",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "checkout_id",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/health": {
      "get": {
        "tags": [
          "Sistema"
        ],
        "summary": "Salud del servicio",
        "description": "Responde `{ status: \"ok\" }` si el proceso está arriba. Sin autenticación; lo usan los health checks del orquestador.",
        "operationId": "Health",
        "responses": {
          "200": {
            "description": "OK"
          }
        }
      }
    },
    "/ready": {
      "get": {
        "tags": [
          "Sistema"
        ],
        "summary": "Disponibilidad del servicio",
        "description": "Responde 200 si hay conexión con Postgres y 503 si no. Sin autenticación; lo usa el readinessProbe del orquestador.",
        "operationId": "Ready",
        "responses": {
          "200": {
            "description": "OK"
          },
          "503": {
            "description": "Service Unavailable"
          }
        }
      }
    },
    "/api/merchants": {
      "post": {
        "tags": [
          "Comercios"
        ],
        "summary": "Registrar un comercio (API)",
        "description": "Alta programática de un comercio con su client de Keycloak. **Sin autenticación** (bootstrap). Devuelve las credenciales de API (`client_id` = id del comercio y `client_secret`) **una sola vez** en `meta`. Para el alta con verificación documental use el flujo de Onboarding.",
        "operationId": "MerchantsRegister",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterMerchantRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        }
      },
      "get": {
        "tags": [
          "Comercios"
        ],
        "summary": "Listar mi comercio",
        "description": "Devuelve el propio comercio del token. Para ver todos use `GET /api/admin/merchants` (`bank-admin`).",
        "operationId": "MerchantsList",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiCollectionDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/merchants/{id}": {
      "get": {
        "tags": [
          "Comercios"
        ],
        "summary": "Ver un comercio",
        "description": "El comercio autenticado solo puede ver el suyo (el `id` debe coincidir con el del token).",
        "operationId": "MerchantsGet",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Comercios"
        ],
        "summary": "Actualizar el perfil del comercio",
        "description": "Cambia datos del perfil (nombre, alias, contacto, logo, color…). Asignar `akua_merchant_id` solo lo puede el administrador (403 para el comercio). Los datos de verificación se cambian por el flujo de KYC.",
        "operationId": "MerchantsUpdateProfile",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateMerchantProfileRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/merchants/{id}/settings": {
      "get": {
        "tags": [
          "Configuración del comercio"
        ],
        "summary": "Ver los ajustes del comercio",
        "description": "Opciones de la cuenta: nombres, país, moneda, modelo de negocio, teléfono y correos de contacto. `country`, `currency` y `business_model` son de solo lectura. Si el comercio aún no tiene ajustes se crean con valores por defecto.",
        "operationId": "MerchantSettingsGet",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Configuración del comercio"
        ],
        "summary": "Actualizar los ajustes del comercio",
        "description": "Actualización parcial: lo que no se envía no cambia. Los correos opcionales, `legal_name` y `phone` se borran enviándolos vacíos o `null`. `legal_name` y `phone` se escriben sobre el propio comercio. Los errores de varios campos vuelven juntos (422).",
        "operationId": "MerchantSettingsUpdate",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateMerchantSettingsRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/merchants/{id}/credentials": {
      "get": {
        "tags": [
          "Configuración del comercio"
        ],
        "summary": "Ver las llaves de API",
        "description": "`client_id` (igual a `cust_id`), los últimos 4 caracteres del secreto (`secret_hint`) y la fecha de la última rotación. El secreto completo no se puede recuperar: rótelo para obtener uno nuevo.",
        "operationId": "MerchantCredentialsGet",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/merchants/{id}/credentials/rotate": {
      "post": {
        "tags": [
          "Configuración del comercio"
        ],
        "summary": "Rotar el secreto de API",
        "description": "Genera un secreto nuevo y lo devuelve **una sola vez** en `meta.secret`; el anterior deja de servir de inmediato.",
        "operationId": "MerchantCredentialsRotate",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/merchants/{id}/ip-allowlist": {
      "get": {
        "tags": [
          "Configuración del comercio"
        ],
        "summary": "Listar las IP permitidas",
        "description": "Lista blanca de IP desde las que se acepta la API con los tokens del comercio. Lista vacía = sin restricción.",
        "operationId": "IpAllowlistList",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiCollectionDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "post": {
        "tags": [
          "Configuración del comercio"
        ],
        "summary": "Agregar una IP permitida",
        "description": "`address` es una IP (IPv4/IPv6) o un rango CIDR, que se guarda normalizado. Una vez hay entradas, la API responde 403 a los tokens del comercio (credenciales de servicio) que lleguen desde IP no listadas. Máximo 50 entradas.",
        "operationId": "IpAllowlistAdd",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AddIpAllowlistEntryRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/merchants/{id}/ip-allowlist/{entryId}": {
      "delete": {
        "tags": [
          "Configuración del comercio"
        ],
        "summary": "Quitar una IP permitida",
        "description": "Elimina la entrada. Si era la última, la API vuelve a aceptar cualquier IP.",
        "operationId": "IpAllowlistRemove",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "entryId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/merchants/{id}/web-checkouts": {
      "get": {
        "tags": [
          "Web checkouts"
        ],
        "summary": "Listar los web checkouts",
        "description": "Los checkouts web del comercio, el más antiguo primero (el `default` creado por la migración queda arriba). `logo` es una URL de lectura (prefirmada de corta vida si el logo se subió al almacenamiento).",
        "operationId": "WebCheckoutsList",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiCollectionDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "post": {
        "tags": [
          "Web checkouts"
        ],
        "summary": "Crear un web checkout",
        "description": "`name` es obligatorio; el resto toma valores por defecto (moneda del comercio, `es`, expiración `1d`, reintentos permitidos). `subdomain` es único globalmente. Se genera una `public_key` de solo lectura. Los errores de varios campos vuelven juntos (422).",
        "operationId": "WebCheckoutsCreate",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebCheckoutRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/merchants/{id}/web-checkouts/{checkoutId}": {
      "get": {
        "tags": [
          "Web checkouts"
        ],
        "summary": "Ver un web checkout",
        "description": "Un checkout del comercio.",
        "operationId": "WebCheckoutsGet",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "checkoutId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Web checkouts"
        ],
        "summary": "Actualizar un web checkout",
        "description": "Actualización parcial: lo que no se envía no cambia; `subdomain`, `response_url`, `confirmation_url`, `support_text` y `logo_key` se borran enviándolos vacíos o `null`. `logo_key` asigna el logo subido con `logo-upload` (se verifica en el almacenamiento: PNG/JPEG/WebP de hasta 2 MB). No se puede desactivar el último checkout activo.",
        "operationId": "WebCheckoutsUpdate",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "checkoutId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebCheckoutRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "delete": {
        "tags": [
          "Web checkouts"
        ],
        "summary": "Eliminar un web checkout",
        "description": "No se puede eliminar el último checkout activo del comercio.",
        "operationId": "WebCheckoutsDelete",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "checkoutId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "204": {
            "description": "No Content"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/merchants/{id}/web-checkouts/{checkoutId}/logo-upload": {
      "post": {
        "tags": [
          "Web checkouts"
        ],
        "summary": "Pedir la URL para subir el logo",
        "description": "Body `{ data: { attributes: { content_type } } }` (también se acepta `{ content_type }`); tipos `image/png`, `image/jpeg` o `image/webp`. Devuelve en `meta` la URL prefirmada (`upload_url`, subir con `PUT` y los `upload_headers`) y la `key`. Después asigne la `key` con `PATCH` (`logo_key`).",
        "operationId": "WebCheckoutsLogoUpload",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "checkoutId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/WebCheckoutLogoUploadRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants": {
      "post": {
        "tags": [
          "Admin · Comercios"
        ],
        "summary": "Registrar un comercio",
        "description": "Alta manual de un comercio por el administrador, con su verificación. Con `create_approved: true` se crea ya aprobado: se provisiona su client de Keycloak y las credenciales (`client_id`, `client_secret`) se devuelven **una sola vez** en `meta`. Si no, queda `pending` y se verifica con las acciones de `Admin · Verificación`.\n\n**Errores:** 422 por campo (correo o documento repetidos, datos inválidos).",
        "operationId": "AdminMerchantsCreate",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminCreateMerchantRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "get": {
        "tags": [
          "Admin · Comercios"
        ],
        "summary": "Listar todos los comercios",
        "description": "Todos los comercios del motor. Requiere `bank-admin`.",
        "operationId": "AdminMerchantsList",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiCollectionDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}": {
      "get": {
        "tags": [
          "Admin · Comercios"
        ],
        "summary": "Ver un comercio",
        "description": "Datos del comercio, incluido su estado de registro en Akua (`akua_registration_status`: `not_registered`, `registered`, `failed`, `sync_pending`).",
        "operationId": "AdminMerchantsGet",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Admin · Comercios"
        ],
        "summary": "Editar un comercio",
        "description": "Cambia solo los campos enviados; los embeds (direcciones, representante, cuenta) se reemplazan completos. Cargar a mano `akua_merchant_id` lo marca como registrado. La verificación abierta sigue lo corregido.",
        "operationId": "AdminMerchantsUpdate",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/AdminUpdateMerchantRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/onboarding": {
      "get": {
        "tags": [
          "Admin · Verificación"
        ],
        "summary": "Ver la verificación de un comercio",
        "description": "Estado global y por sección, documentos vigentes, documentos requeridos y la auditoría completa de decisiones.",
        "operationId": "AdminOnboardingGet",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/start-review": {
      "post": {
        "tags": [
          "Admin · Verificación"
        ],
        "summary": "Iniciar la revisión",
        "description": "Pasa la verificación de `submitted` a `in_review`: el comercio ve que se están validando sus datos.\n\nEl cuerpo es opcional: `{ data: { attributes: { note } } }`. Una transición que el estado actual no permite responde 409.",
        "operationId": "AdminMerchantsStartReview",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/AdminReviewRequest"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/request-changes": {
      "post": {
        "tags": [
          "Admin · Verificación"
        ],
        "summary": "Pedir cambios",
        "description": "Devuelve la verificación al comercio (`changes_requested`) con una **nota obligatoria** que él verá; puede corregir y reenviar. En una actualización, el comercio sigue operando con lo aprobado.\n\nEl cuerpo es opcional: `{ data: { attributes: { note } } }`. Una transición que el estado actual no permite responde 409.",
        "operationId": "AdminMerchantsRequestChanges",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/AdminReviewRequest"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/approve": {
      "post": {
        "tags": [
          "Admin · Verificación"
        ],
        "summary": "Aprobar",
        "description": "**Verificación inicial:** el comercio pasa a `active`, se provisiona su client de Keycloak y las credenciales (`client_id`, `client_secret`) se devuelven **una sola vez** en `meta`. **Actualización:** los cambios pasan a regir (reemplazan la revisión vigente, se aplican al comercio) y, si ya estaba en Akua, queda `sync_pending`.\n\nEl cuerpo es opcional: `{ data: { attributes: { note } } }`. Una transición que el estado actual no permite responde 409.",
        "operationId": "AdminMerchantsApprove",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/AdminReviewRequest"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/reject": {
      "post": {
        "tags": [
          "Admin · Verificación"
        ],
        "summary": "Rechazar",
        "description": "Rechaza la verificación con una **nota obligatoria**. En la inicial el comercio se cierra y no podrá operar; en una actualización solo se descarta (sigue operando con lo aprobado).\n\nEl cuerpo es opcional: `{ data: { attributes: { note } } }`. Una transición que el estado actual no permite responde 409.",
        "operationId": "AdminMerchantsReject",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/AdminReviewRequest"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/suspend": {
      "post": {
        "tags": [
          "Admin · Verificación"
        ],
        "summary": "Suspender el comercio",
        "description": "El comercio activo deja de poder iniciar sesión y cobrar (se deshabilita su client de Keycloak) hasta que se reactive.\n\nEl cuerpo es opcional: `{ data: { attributes: { note } } }`. Una transición que el estado actual no permite responde 409.",
        "operationId": "AdminMerchantsSuspend",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/AdminReviewRequest"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/reactivate": {
      "post": {
        "tags": [
          "Admin · Verificación"
        ],
        "summary": "Reactivar el comercio",
        "description": "Vuelve a habilitar a un comercio suspendido.\n\nEl cuerpo es opcional: `{ data: { attributes: { note } } }`. Una transición que el estado actual no permite responde 409.",
        "operationId": "AdminMerchantsReactivate",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/AdminReviewRequest"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/close": {
      "post": {
        "tags": [
          "Admin · Verificación"
        ],
        "summary": "Cerrar el comercio",
        "description": "Cierre **definitivo**: el comercio no podrá reactivarse.\n\nEl cuerpo es opcional: `{ data: { attributes: { note } } }`. Una transición que el estado actual no permite responde 409.",
        "operationId": "AdminMerchantsClose",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "type": "null"
                  },
                  {
                    "$ref": "#/components/schemas/AdminReviewRequest"
                  }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/akua-registration": {
      "post": {
        "tags": [
          "Admin · Akua"
        ],
        "summary": "Registrar el comercio en Akua",
        "description": "Registro **opcional** del comercio activo como merchant en Akua (`POST /v1/merchants`). Valida antes que no falte nada y lo dice en español (sitio web con canal ecommerce; calle, **número**, **código postal**, ciudad y departamento de ubicación; representante con documento). Envía además lo aprobado en el KYC: accionistas, nacionalidad y nacimiento del representante, retenciones y responsabilidades fiscales.\n\nIdempotente: el id que se manda a Akua es determinístico por comercio. Un rechazo de Akua responde 422 con su mensaje y queda en `akua_registration_error` para corregir y reintentar; 409 si ya está registrado.",
        "operationId": "AdminAkuaRegister",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/akua-sync": {
      "post": {
        "tags": [
          "Admin · Akua"
        ],
        "summary": "Sincronizar cambios con Akua",
        "description": "Envía a Akua lo aprobado después del registro (`PUT /v1/merchants/{id}`, que reemplaza el comercio completo). Aplica cuando el comercio está `sync_pending`, es decir, se aprobó una actualización del KYC y Akua tiene la versión anterior. Si Akua rechaza, el comercio sigue `sync_pending` con el motivo guardado y no deja de operar. 409 si no hay nada pendiente.",
        "operationId": "AdminAkuaSync",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/sections/{section}": {
      "patch": {
        "tags": [
          "Admin · Verificación"
        ],
        "summary": "Marcar el estado de una sección",
        "description": "Cambia una sección de la verificación a `pending`, `in_review`, `verified` o `rejected` (esta última exige nota). Secciones: `personal`, `business`, `location`, `bank`, `documents`, `tax`, `activity`, `shareholders`, `financial`, `compliance`.",
        "operationId": "AdminOnboardingSetSection",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "section",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SectionReviewRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/documents": {
      "post": {
        "tags": [
          "Admin · Verificación"
        ],
        "summary": "Pedir la URL para subir un documento",
        "description": "Igual que el flujo del comercio, sobre el expediente de cualquier comercio: devuelve la URL prefirmada en `meta.upload`.",
        "operationId": "AdminDocumentsRequestUpload",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentUploadRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/documents/{docId}/confirm": {
      "post": {
        "tags": [
          "Admin · Verificación"
        ],
        "summary": "Confirmar la subida de un documento",
        "description": "Verifica el archivo en el almacenamiento y deja el documento `uploaded`.",
        "operationId": "AdminDocumentsConfirm",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "docId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/documents/{docId}/download": {
      "get": {
        "tags": [
          "Admin · Verificación"
        ],
        "summary": "Descargar un documento",
        "description": "URL prefirmada de corta vida; cada descarga queda auditada.",
        "operationId": "AdminDocumentsDownload",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "docId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/documents/{docId}/review": {
      "patch": {
        "tags": [
          "Admin · Verificación"
        ],
        "summary": "Aprobar o rechazar un documento",
        "description": "`status`: `approved` o `rejected` (el rechazo exige una nota que verá el comercio).",
        "operationId": "AdminDocumentsReview",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "docId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentReviewRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/payment-links": {
      "get": {
        "tags": [
          "Admin · Cobros"
        ],
        "summary": "Links de un comercio",
        "description": "Los links de pago de cualquier comercio. `filter[state][not_eq]` funciona igual que en `GET /api/payment-links`.",
        "operationId": "AdminMerchantPaymentLinks",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiCollectionDocument"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/payment-links/{linkId}": {
      "get": {
        "tags": [
          "Admin · Cobros"
        ],
        "summary": "Un link de un comercio",
        "description": "Un link de pago de cualquier comercio.",
        "operationId": "AdminMerchantPaymentLink",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "linkId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/onboarding/register": {
      "post": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Registrar mi comercio",
        "description": "Auto-registro público: crea el comercio en estado `pending`, su verificación en borrador y un usuario de Keycloak con el correo y la contraseña indicados. **No emite credenciales de API**: eso ocurre cuando el administrador aprueba.\n\n**Entrada:** `email`, `password` (mínimo 8 caracteres), `owner_full_name`, `person_type` (`legal` o `natural`), `name` (nombre del comercio), `tax_id` y `tax_id_type` (por defecto `nit`), `accepted_terms`.\n\n**Después:** inicie sesión con el correo y la contraseña y use `GET /api/onboarding` para ver el expediente.\n\n**Errores:** 422 con el campo en `source.pointer` (correo o documento ya registrados, clave corta, términos sin aceptar); 429 si se supera el límite por IP (5 solicitudes cada 10 minutos).",
        "operationId": "OnboardingRegister",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SelfRegisterRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "429": {
            "description": "Too Many Requests",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/api/onboarding": {
      "get": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Ver mi verificación",
        "description": "Estado de la verificación del propio comercio: estado global, estado de cada sección, documentos subidos y requeridos según el tipo de persona, nota del revisor y el comercio completo en `meta.merchant`. Si hay una actualización abierta devuelve esa; si no, la aprobada vigente.\n\nPara el documento KYC completo use `GET /api/onboarding/kyc`.",
        "operationId": "OnboardingGet",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/onboarding/sections/{section}": {
      "put": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Guardar una sección (formato original)",
        "description": "Forma original del asistente: guarda `personal`, `business`, `location` o `bank` con los campos del comercio (representante, nombre, ubicación, cuenta). Valida lo que Akua exigirá después y deja la sección `in_review`. El correo y el NIT no se editan.\n\nEl KYC completo se guarda con `PUT /api/onboarding/kyc`; ambos escriben sobre el mismo documento. **Solo en `draft` o `changes_requested`** (con la verificación enviada o resuelta responde 409).",
        "operationId": "OnboardingSaveSection",
        "parameters": [
          {
            "name": "section",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/SaveSectionRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/onboarding/submit": {
      "post": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Enviar a revisión",
        "description": "Envía la verificación abierta. Exige los campos que las reglas del banco marcan como obligatorios (por defecto, lo que Akua ya pedía) y que ninguna sección esté rechazada; los documentos son opcionales.\n\n- **Verificación inicial:** pasa a `submitted` y queda bloqueada hasta que el administrador responda.\n- **Actualización:** se calcula el diff contra lo aprobado. Si solo cambian campos de política `direct` se **aprueba sola** (`state: approved`); si cambia alguno con revisión queda `submitted`. Sin cambios responde 422.\n\n**Errores:** 422 con un error por cada campo obligatorio faltante (`source.pointer` = `/data/attributes/<seccion.grupo.campo>`); 409 si ya está enviada.",
        "operationId": "OnboardingSubmit",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/onboarding/documents": {
      "post": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Pedir la URL para subir un documento",
        "description": "Primer paso de la subida: registra el documento (`type`, `file_name`, `content_type`) y devuelve una **URL prefirmada** en `meta.upload` (`url` y `headers`). Suba el archivo con `PUT` directo a esa URL y confirme con `POST /api/onboarding/documents/{docId}/confirm`.\n\nTipos según la persona — jurídica: `rut`, `camara_comercio_existencia`, `formato_vinculacion`, `estados_financieros`; natural: `cedula_anverso`, `cedula_reverso`, `rut`, `camara_comercio`, `formato_vinculacion`. Archivos PDF, JPG o PNG de hasta 10 MB. Reenviar el mismo tipo reemplaza al anterior.",
        "operationId": "OnboardingRequestDocument",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/DocumentUploadRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/onboarding/documents/{docId}/confirm": {
      "post": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Confirmar la subida de un documento",
        "description": "Tercer paso: el motor verifica en el almacenamiento que el archivo exista, que su tipo y tamaño sean válidos y guarda su huella. El documento queda `uploaded` y la sección de documentos pasa a revisión.",
        "operationId": "OnboardingConfirmDocument",
        "parameters": [
          {
            "name": "docId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/onboarding/documents/{docId}/download": {
      "get": {
        "tags": [
          "Onboarding"
        ],
        "summary": "Descargar un documento",
        "description": "Devuelve una URL prefirmada de corta vida (`attributes.url`) para abrir el archivo. Cada descarga queda auditada.",
        "operationId": "OnboardingDownloadDocument",
        "parameters": [
          {
            "name": "docId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/catalogs": {
      "get": {
        "tags": [
          "Catálogos"
        ],
        "summary": "Listar catálogos",
        "description": "Los catálogos disponibles (`ciiu`, `ocupacion`, `nacionalidad`, `tipo_documento`, `tipo_sociedad`, `resp_renta`…), con su descripción y, si dependen de otro, `parent_catalog`.",
        "operationId": "CatalogsList",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiCollectionDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/catalogs/{key}/items": {
      "get": {
        "tags": [
          "Catálogos"
        ],
        "summary": "Listar ítems de un catálogo",
        "description": "Ítems activos ordenados por `sort_order`. El valor que guardan los formularios es el **código** (`code`).\n\n**Parámetros:** `q` busca en código y etiqueta sin distinguir mayúsculas; `parent_code` filtra los de un padre (p. ej. subsectores de un sector); `limit` acota la respuesta; `include_inactive=true` incluye los desactivados (solo `bank-admin`).",
        "operationId": "CatalogsListItems",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "parent_code",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "q",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "pattern": "^-?(?:0|[1-9]\\d*)$",
              "type": [
                "integer",
                "string"
              ],
              "format": "int32"
            }
          },
          {
            "name": "include_inactive",
            "in": "query",
            "schema": {
              "type": "boolean",
              "default": false
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiCollectionDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/catalogs/{key}/items": {
      "post": {
        "tags": [
          "Admin · Catálogos"
        ],
        "summary": "Crear un ítem de catálogo",
        "description": "Agrega un ítem (`code`, `label`, `parent_code`, `sort_order`, `metadata`). El código no se puede cambiar después: es lo que guardan los formularios. En un catálogo dependiente el `parent_code` debe existir. Queda auditado. 422 si el código ya existe.",
        "operationId": "AdminCatalogsCreateItem",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CreateCatalogItemRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/catalogs/{key}/items/{code}": {
      "patch": {
        "tags": [
          "Admin · Catálogos"
        ],
        "summary": "Editar o desactivar un ítem",
        "description": "Cambia etiqueta, orden, padre, metadatos o `active`. **No hay borrado**: desactivar retira el ítem de las opciones sin invalidar lo ya aprobado. Cada cambio queda auditado con el antes y el después.",
        "operationId": "AdminCatalogsUpdateItem",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateCatalogItemRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/catalogs/{key}/items/{code}/audit": {
      "get": {
        "tags": [
          "Admin · Catálogos"
        ],
        "summary": "Historial de un ítem",
        "description": "Cambios del ítem con el estado anterior y el posterior, quién y cuándo.",
        "operationId": "AdminCatalogsItemAudit",
        "parameters": [
          {
            "name": "key",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "code",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiCollectionDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/kyc/schema": {
      "get": {
        "tags": [
          "KYC"
        ],
        "summary": "Esquema del formulario KYC y reglas",
        "description": "Entrega la estructura del formulario de un tipo de persona para armarlo sin código por campo: secciones → grupos → campos, con `type` (`text`, `email`, `phone`, `digits`, `date`, `boolean`, `money`, `percent`, `select`), `catalog` (clave del catálogo, ver `GET /api/catalogs/{key}/items`) u `options`, `when` (el campo solo aplica si otro del mismo grupo vale algo), `computed` (lo calcula el servidor: DV del NIT, totales), `immutable` (identidad, no se edita) y `max_length`. Los grupos con `repeatable` son listas (accionistas, sucursales).\n\n`rules` trae, por ruta `seccion.grupo.campo`, si el campo es `required`, su `change_policy` (`direct`: un cambio posterior a la aprobación se aplica solo; `review`: pasa por un revisor) y si es `visible`.\n\n**Parámetro:** `person_type` = `legal` (por defecto) o `natural`.",
        "operationId": "KycGetSchema",
        "parameters": [
          {
            "name": "person_type",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/onboarding/kyc": {
      "get": {
        "tags": [
          "KYC"
        ],
        "summary": "Ver mi documento KYC",
        "description": "Documento KYC del comercio: la revisión abierta o, si no hay, la aprobada vigente. `attributes.data` es el documento (`{ seccion: { grupo: { campo: valor } } }`, con listas en los grupos repetibles), `sections` el estado de cada sección, `kind` (`initial` o `update`), `state` y `changes` (el diff, si ya se envió).\n\nLos datos sensibles se entregan en claro al propio comercio.",
        "operationId": "KycGetOwn",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "put": {
        "tags": [
          "KYC"
        ],
        "summary": "Guardar secciones del KYC",
        "description": "Guarda una o varias secciones: `{ data: { attributes: { sections: { activity: { main: { ciiu: 'EF' } } } } } }`.\n\n**Reemplaza los grupos recibidos** (mande el grupo completo; un campo que no va, se borra) y deja las secciones tocadas `in_review`. Se valida con el esquema: tipos, pertenencia a catálogo activo, condiciones, máximos de las listas, fechas no futuras. Los campos calculados y los inmutables se ignoran. Los obligatorios se exigen al **enviar**, no al guardar.\n\nEn la verificación inicial también actualiza el comercio (nombre, teléfono, ubicación, cuenta…); en una actualización no: eso ocurre al aprobarla. **Solo en `draft` o `changes_requested`.**\n\n**Errores:** 422 con **todos** los errores a la vez, uno por campo, con su ruta en `source.pointer` (en listas con índice: `shareholders.items[1].percentage`); 409 si la verificación está enviada.",
        "operationId": "KycSaveOwn",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonObject"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/onboarding/kyc/updates": {
      "post": {
        "tags": [
          "KYC"
        ],
        "summary": "Actualizar mi información",
        "description": "Con la verificación aprobada, abre una **actualización**: un borrador copiado de la revisión vigente. Mientras se revisa, el comercio sigue operando con lo aprobado. Edite con `PUT /api/onboarding/kyc`, vea el diff con `GET /api/onboarding/kyc/changes` y envíe con `POST /api/onboarding/submit`.\n\n**Errores:** 422 si no hay una verificación aprobada o ya hay otra abierta.",
        "operationId": "KycStartUpdate",
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/onboarding/kyc/updates/current": {
      "delete": {
        "tags": [
          "KYC"
        ],
        "summary": "Retirar la actualización abierta",
        "description": "Descarta la actualización que aún no se resolvió (`withdrawn`). Lo aprobado no cambia y el comercio puede abrir otra. 422 si no hay una actualización abierta.",
        "operationId": "KycWithdrawUpdate",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/onboarding/kyc/changes": {
      "get": {
        "tags": [
          "KYC"
        ],
        "summary": "Ver los cambios de mi actualización",
        "description": "Diff de la actualización abierta contra la revisión en la que se basa: por ruta, `from`, `to` y `policy` (`direct` o `review`). `requires_review` indica si algún cambio necesita revisor; si todos son `direct`, el envío se aprobará solo. Las listas repetibles se comparan completas.",
        "operationId": "KycGetOwnChanges",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/onboarding/kyc/revisions": {
      "get": {
        "tags": [
          "KYC"
        ],
        "summary": "Historial de mis revisiones",
        "description": "Todas las revisiones del comercio, la más reciente primero: número, tipo, estado, revisión base, fechas, revisor y diff.",
        "operationId": "KycListOwnRevisions",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiCollectionDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/kyc": {
      "get": {
        "tags": [
          "Admin · KYC"
        ],
        "summary": "Ver el KYC de un comercio",
        "description": "Documento KYC completo del comercio (revisión abierta o vigente). Incluye identificadores, cuenta bancaria y datos financieros: **cada lectura queda auditada** (`kyc_viewed`). Requiere `bank-admin`.",
        "operationId": "AdminKycGet",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "put": {
        "tags": [
          "Admin · KYC"
        ],
        "summary": "Corregir el KYC de un comercio",
        "description": "Igual que `PUT /api/onboarding/kyc` pero sobre cualquier comercio y **en cualquier estado**; no cambia el estado de las secciones (eso lo decide la verificación). Reemplaza los grupos recibidos y devuelve todos los errores de campo a la vez.",
        "operationId": "AdminKycSave",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonObject"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/kyc/changes": {
      "get": {
        "tags": [
          "Admin · KYC"
        ],
        "summary": "Ver el diff de una actualización",
        "description": "Diff de la actualización de un comercio contra lo aprobado, para decidir. Los valores sensibles (identificadores, cuenta, montos) vienen **enmascarados** (`•••• 3456`); el documento completo se lee con `GET /api/admin/merchants/{id}/kyc`, que queda auditado. Una actualización ya resuelta muestra el diff que quedó guardado.",
        "operationId": "AdminKycChanges",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/merchants/{id}/kyc/revisions": {
      "get": {
        "tags": [
          "Admin · KYC"
        ],
        "summary": "Historial de revisiones de un comercio",
        "description": "Todas las revisiones del comercio, la más reciente primero: de dónde viene lo que rige hoy y qué se aprobó antes.",
        "operationId": "AdminKycRevisions",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiCollectionDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/admin/kyc/rules": {
      "put": {
        "tags": [
          "Admin · KYC"
        ],
        "summary": "Definir la regla de un campo",
        "description": "Define, por tipo de persona y ruta `seccion.grupo.campo`, si el campo es **obligatorio** al enviar, su **política de cambio** (`direct` o `review`) y si es **visible**. Aplica de inmediato, sin desplegar. Lo que no tiene regla es opcional, visible y con revisión.\n\n**Entrada:** `person_type`, `path`, `required`, `change_policy`, `visible`. **Errores:** 422 si la ruta no existe, el campo es calculado o un obligatorio queda oculto.",
        "operationId": "AdminKycUpsertRule",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/JsonObject"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/payment-links": {
      "post": {
        "tags": [
          "Links de pago"
        ],
        "summary": "Crear un link de pago",
        "description": "Crea un link de cobro del comercio. Requiere `concept`, `description` y `amount`; el resto tiene valor por defecto (`currency` COP, IVA 19 %, un solo pago, medio `cuentas_crezcamos`). El comercio debe tener `akua_merchant_id` para poder cobrar.\n\n`customer_data_policy` y `shipping_data_policy` (`hidden`, `optional`, `required`) deciden qué pide el checkout al pagador. La respuesta trae `url`, la dirección pública `/l/{token}` que abre el pagador.\n\n**Errores:** 422 con el campo inválido.",
        "operationId": "PaymentLinksGenerate",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/GeneratePaymentLinkRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "get": {
        "tags": [
          "Links de pago"
        ],
        "summary": "Listar mis links",
        "description": "Links del comercio autenticado. `filter[state][not_eq]=<estado>` excluye un estado (`active`, `revoked`, `expired`, `paid`…); un estado desconocido responde 400.",
        "operationId": "PaymentLinksList",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiCollectionDocument"
                }
              }
            }
          },
          "400": {
            "description": "Bad Request",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/payment-links/{id}": {
      "get": {
        "tags": [
          "Links de pago"
        ],
        "summary": "Ver un link",
        "description": "Un link del comercio autenticado, con su estado, montos calculados y URL pública.",
        "operationId": "PaymentLinksGet",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/payment-links/{id}/revoke": {
      "patch": {
        "tags": [
          "Links de pago"
        ],
        "summary": "Revocar un link",
        "description": "Desactiva el link: el pagador deja de poder usarlo. 409 si su estado no admite revocarlo.",
        "operationId": "PaymentLinksRevoke",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/payment-links/{id}/reactivate": {
      "patch": {
        "tags": [
          "Links de pago"
        ],
        "summary": "Reactivar un link",
        "description": "Vuelve a activar un link revocado. 409 si su estado no admite reactivarlo.",
        "operationId": "PaymentLinksReactivate",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "403": {
            "description": "Forbidden",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "409": {
            "description": "Conflict",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/merchant-webhooks": {
      "post": {
        "tags": [
          "Webhooks del comercio"
        ],
        "summary": "Registrar un webhook",
        "description": "Registra la URL a la que el motor notificará los eventos de pago del comercio, con los tipos de evento que le interesan. El **secreto de firma** se devuelve **una sola vez** en `meta.secret` (nunca como atributo): guárdelo para verificar las notificaciones.",
        "operationId": "MerchantWebhooksRegister",
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/RegisterMerchantWebhookRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "get": {
        "tags": [
          "Webhooks del comercio"
        ],
        "summary": "Listar mis webhooks",
        "description": "Webhooks del comercio autenticado.",
        "operationId": "MerchantWebhooksList",
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiCollectionDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/merchant-webhooks/{id}": {
      "get": {
        "tags": [
          "Webhooks del comercio"
        ],
        "summary": "Ver un webhook",
        "description": "Un webhook del comercio autenticado (sin su secreto).",
        "operationId": "MerchantWebhooksGet",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      },
      "patch": {
        "tags": [
          "Webhooks del comercio"
        ],
        "summary": "Cambiar la configuración de un webhook",
        "description": "Cambia la URL, los eventos suscritos o si está activo. El secreto no cambia (use `rotate-secret`).",
        "operationId": "MerchantWebhooksUpdate",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/UpdateMerchantWebhookConfigRequest"
              }
            }
          },
          "required": true
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "422": {
            "description": "Unprocessable Entity",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/api/merchant-webhooks/{id}/rotate-secret": {
      "patch": {
        "tags": [
          "Webhooks del comercio"
        ],
        "summary": "Rotar el secreto de firma",
        "description": "Genera un secreto nuevo y lo devuelve **una sola vez** en `meta.secret`; el anterior deja de servir.",
        "operationId": "MerchantWebhooksRotateSecret",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiDocument"
                }
              }
            }
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          },
          "404": {
            "description": "Not Found",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        },
        "security": [
          {
            "Bearer": []
          }
        ]
      }
    },
    "/webhooks/akua/payments": {
      "post": {
        "tags": [
          "Webhooks entrantes"
        ],
        "summary": "Webhook de Akua: payments",
        "description": "Notificación de Akua. Se autentica con la **firma** del proveedor (cabecera de firma con timestamp; se rechaza si no verifica o expiró), no con un JWT. Es idempotente: reenvíos del mismo evento no repiten el efecto, y un evento fuera de orden no hace que el proveedor reintente indefinidamente. Responde 200 salvo firma inválida (401).",
        "operationId": "WebhookAkuaPayments",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/akua/payment-approved": {
      "post": {
        "tags": [
          "Webhooks entrantes"
        ],
        "summary": "Webhook de Akua: payment-approved",
        "description": "Notificación de Akua. Se autentica con la **firma** del proveedor (cabecera de firma con timestamp; se rechaza si no verifica o expiró), no con un JWT. Es idempotente: reenvíos del mismo evento no repiten el efecto, y un evento fuera de orden no hace que el proveedor reintente indefinidamente. Responde 200 salvo firma inválida (401).",
        "operationId": "WebhookAkuaPaymentApproved",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/akua/payment-rejected": {
      "post": {
        "tags": [
          "Webhooks entrantes"
        ],
        "summary": "Webhook de Akua: payment-rejected",
        "description": "Notificación de Akua. Se autentica con la **firma** del proveedor (cabecera de firma con timestamp; se rechaza si no verifica o expiró), no con un JWT. Es idempotente: reenvíos del mismo evento no repiten el efecto, y un evento fuera de orden no hace que el proveedor reintente indefinidamente. Responde 200 salvo firma inválida (401).",
        "operationId": "WebhookAkuaPaymentRejected",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/akua/payment-failed": {
      "post": {
        "tags": [
          "Webhooks entrantes"
        ],
        "summary": "Webhook de Akua: payment-failed",
        "description": "Notificación de Akua. Se autentica con la **firma** del proveedor (cabecera de firma con timestamp; se rechaza si no verifica o expiró), no con un JWT. Es idempotente: reenvíos del mismo evento no repiten el efecto, y un evento fuera de orden no hace que el proveedor reintente indefinidamente. Responde 200 salvo firma inválida (401).",
        "operationId": "WebhookAkuaPaymentFailed",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/akua/payment-refund": {
      "post": {
        "tags": [
          "Webhooks entrantes"
        ],
        "summary": "Webhook de Akua: payment-refund",
        "description": "Notificación de Akua. Se autentica con la **firma** del proveedor (cabecera de firma con timestamp; se rechaza si no verifica o expiró), no con un JWT. Es idempotente: reenvíos del mismo evento no repiten el efecto, y un evento fuera de orden no hace que el proveedor reintente indefinidamente. Responde 200 salvo firma inválida (401).",
        "operationId": "WebhookAkuaPaymentRefund",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/akua/payment-chargeback": {
      "post": {
        "tags": [
          "Webhooks entrantes"
        ],
        "summary": "Webhook de Akua: payment-chargeback",
        "description": "Notificación de Akua. Se autentica con la **firma** del proveedor (cabecera de firma con timestamp; se rechaza si no verifica o expiró), no con un JWT. Es idempotente: reenvíos del mismo evento no repiten el efecto, y un evento fuera de orden no hace que el proveedor reintente indefinidamente. Responde 200 salvo firma inválida (401).",
        "operationId": "WebhookAkuaPaymentChargeback",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        }
      }
    },
    "/webhooks/crezcamos/pse-payments": {
      "post": {
        "tags": [
          "Webhooks entrantes"
        ],
        "summary": "Webhook de Crezcamos-PSE",
        "description": "Notificación del estado de un pago PSE liquidado a través de Akua. Se autentica con la firma de Crezcamos, no con un JWT. Responde 200 salvo firma inválida (401).",
        "operationId": "WebhookCrezcamosPse",
        "responses": {
          "200": {
            "description": "OK"
          },
          "401": {
            "description": "Unauthorized",
            "content": {
              "application/vnd.api+json": {
                "schema": {
                  "$ref": "#/components/schemas/JsonApiErrorDocument"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "schemas": {
      "AddIpAllowlistEntryRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/AddIpAllowlistEntryRequestData"
          }
        }
      },
      "AddIpAllowlistEntryRequestAttributes": {
        "required": [
          "address",
          "description"
        ],
        "type": "object",
        "properties": {
          "address": {
            "type": [
              "null",
              "string"
            ]
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "AddIpAllowlistEntryRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/AddIpAllowlistEntryRequestAttributes"
          }
        }
      },
      "AdminCreateMerchantRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/AdminCreateMerchantRequestData"
          }
        }
      },
      "AdminCreateMerchantRequestAttributes": {
        "required": [
          "name",
          "alias",
          "email",
          "phone",
          "website",
          "logo",
          "primary_color",
          "support_text",
          "activity",
          "channel",
          "default_currency",
          "supported_currencies",
          "tax_id",
          "tax_id_type",
          "legal_name",
          "notes",
          "person_type",
          "address",
          "location_address",
          "legal_representative",
          "payout_information",
          "create_approved"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "alias": {
            "type": [
              "null",
              "string"
            ]
          },
          "email": {
            "type": "string"
          },
          "phone": {
            "type": [
              "null",
              "string"
            ]
          },
          "website": {
            "type": [
              "null",
              "string"
            ]
          },
          "logo": {
            "type": [
              "null",
              "string"
            ]
          },
          "primary_color": {
            "type": [
              "null",
              "string"
            ]
          },
          "support_text": {
            "type": [
              "null",
              "string"
            ]
          },
          "activity": {
            "type": [
              "null",
              "string"
            ]
          },
          "channel": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            }
          },
          "default_currency": {
            "type": [
              "null",
              "string"
            ]
          },
          "supported_currencies": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            }
          },
          "tax_id": {
            "type": "string"
          },
          "tax_id_type": {
            "type": [
              "null",
              "string"
            ]
          },
          "legal_name": {
            "type": [
              "null",
              "string"
            ]
          },
          "notes": {
            "type": [
              "null",
              "string"
            ]
          },
          "person_type": {
            "type": [
              "null",
              "string"
            ]
          },
          "address": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/MerchantAddress"
              }
            ]
          },
          "location_address": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/MerchantAddress"
              }
            ]
          },
          "legal_representative": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/LegalRepresentative"
              }
            ]
          },
          "payout_information": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/PayoutInformation"
              }
            ]
          },
          "create_approved": {
            "type": [
              "null",
              "boolean"
            ]
          }
        }
      },
      "AdminCreateMerchantRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/AdminCreateMerchantRequestAttributes"
          }
        }
      },
      "AdminReviewRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/AdminReviewRequestData"
              }
            ]
          }
        }
      },
      "AdminReviewRequestAttributes": {
        "required": [
          "note"
        ],
        "type": "object",
        "properties": {
          "note": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "AdminReviewRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/AdminReviewRequestAttributes"
              }
            ]
          }
        }
      },
      "AdminUpdateMerchantRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/AdminUpdateMerchantRequestData"
          }
        }
      },
      "AdminUpdateMerchantRequestAttributes": {
        "required": [
          "name",
          "alias",
          "email",
          "phone",
          "website",
          "logo",
          "primary_color",
          "support_text",
          "activity",
          "legal_name",
          "notes",
          "akua_merchant_id",
          "person_type",
          "channel",
          "default_currency",
          "supported_currencies",
          "address",
          "location_address",
          "legal_representative",
          "payout_information"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "alias": {
            "type": [
              "null",
              "string"
            ]
          },
          "email": {
            "type": [
              "null",
              "string"
            ]
          },
          "phone": {
            "type": [
              "null",
              "string"
            ]
          },
          "website": {
            "type": [
              "null",
              "string"
            ]
          },
          "logo": {
            "type": [
              "null",
              "string"
            ]
          },
          "primary_color": {
            "type": [
              "null",
              "string"
            ]
          },
          "support_text": {
            "type": [
              "null",
              "string"
            ]
          },
          "activity": {
            "type": [
              "null",
              "string"
            ]
          },
          "legal_name": {
            "type": [
              "null",
              "string"
            ]
          },
          "notes": {
            "type": [
              "null",
              "string"
            ]
          },
          "akua_merchant_id": {
            "type": [
              "null",
              "string"
            ]
          },
          "person_type": {
            "type": [
              "null",
              "string"
            ]
          },
          "channel": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            }
          },
          "default_currency": {
            "type": [
              "null",
              "string"
            ]
          },
          "supported_currencies": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            }
          },
          "address": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/MerchantAddress"
              }
            ]
          },
          "location_address": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/MerchantAddress"
              }
            ]
          },
          "legal_representative": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/LegalRepresentative"
              }
            ]
          },
          "payout_information": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/PayoutInformation"
              }
            ]
          }
        }
      },
      "AdminUpdateMerchantRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/AdminUpdateMerchantRequestAttributes"
          }
        }
      },
      "CreateCatalogItemRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/CreateCatalogItemRequestData"
          }
        }
      },
      "CreateCatalogItemRequestAttributes": {
        "required": [
          "code",
          "label",
          "parent_code",
          "sort_order",
          "metadata"
        ],
        "type": "object",
        "properties": {
          "code": {
            "type": "string"
          },
          "label": {
            "type": "string"
          },
          "parent_code": {
            "type": [
              "null",
              "string"
            ]
          },
          "sort_order": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "metadata": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/JsonElement"
              }
            ]
          }
        }
      },
      "CreateCatalogItemRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/CreateCatalogItemRequestAttributes"
          }
        }
      },
      "DocumentReviewRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/DocumentReviewRequestData"
          }
        }
      },
      "DocumentReviewRequestAttributes": {
        "required": [
          "status",
          "note"
        ],
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "note": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "DocumentReviewRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/DocumentReviewRequestAttributes"
          }
        }
      },
      "DocumentUploadRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/DocumentUploadRequestData"
          }
        }
      },
      "DocumentUploadRequestAttributes": {
        "required": [
          "type",
          "file_name",
          "content_type"
        ],
        "type": "object",
        "properties": {
          "type": {
            "type": "string"
          },
          "file_name": {
            "type": "string"
          },
          "content_type": {
            "type": "string"
          }
        }
      },
      "DocumentUploadRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/DocumentUploadRequestAttributes"
          }
        }
      },
      "GeneratePaymentLinkRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/GeneratePaymentLinkRequestData"
          }
        }
      },
      "GeneratePaymentLinkRequestAttributes": {
        "required": [
          "concept",
          "description",
          "reference",
          "currency",
          "amount",
          "vat_enabled",
          "vat_rate",
          "consumption_tax_enabled",
          "consumption_tax_rate",
          "tip_amount",
          "extra_label",
          "extra_value",
          "max_payment_count",
          "expires_at",
          "confirmation_url",
          "thank_you_url",
          "images",
          "spec_document_url",
          "requires_shipping",
          "customer_data_policy",
          "accepted_payment_methods",
          "shipping_data_policy"
        ],
        "type": "object",
        "properties": {
          "concept": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "reference": {
            "type": [
              "null",
              "string"
            ]
          },
          "currency": {
            "type": [
              "null",
              "string"
            ]
          },
          "amount": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "number",
              "string"
            ],
            "format": "double"
          },
          "vat_enabled": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "vat_rate": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "format": "double"
          },
          "consumption_tax_enabled": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "consumption_tax_rate": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "format": "double"
          },
          "tip_amount": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "format": "double"
          },
          "extra_label": {
            "type": [
              "null",
              "string"
            ]
          },
          "extra_value": {
            "pattern": "^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$",
            "type": [
              "null",
              "number",
              "string"
            ],
            "format": "double"
          },
          "max_payment_count": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "expires_at": {
            "type": "string",
            "format": "date-time"
          },
          "confirmation_url": {
            "type": [
              "null",
              "string"
            ]
          },
          "thank_you_url": {
            "type": [
              "null",
              "string"
            ]
          },
          "images": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            }
          },
          "spec_document_url": {
            "type": [
              "null",
              "string"
            ]
          },
          "requires_shipping": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "customer_data_policy": {
            "type": [
              "null",
              "string"
            ]
          },
          "accepted_payment_methods": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            }
          },
          "shipping_data_policy": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "GeneratePaymentLinkRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/GeneratePaymentLinkRequestAttributes"
          }
        }
      },
      "JsonApiCollectionDocument": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JsonApiResource"
            }
          }
        }
      },
      "JsonApiDocument": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/JsonApiResource"
          },
          "meta": {}
        }
      },
      "JsonApiError": {
        "required": [
          "status",
          "title"
        ],
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "detail": {
            "type": [
              "null",
              "string"
            ]
          },
          "source": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/JsonApiErrorSource"
              }
            ]
          }
        }
      },
      "JsonApiErrorDocument": {
        "required": [
          "errors"
        ],
        "type": "object",
        "properties": {
          "errors": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/JsonApiError"
            }
          }
        }
      },
      "JsonApiErrorSource": {
        "type": "object",
        "properties": {
          "pointer": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "JsonApiResource": {
        "required": [
          "type",
          "id",
          "attributes"
        ],
        "type": "object",
        "properties": {
          "type": {
            "type": "string"
          },
          "id": {
            "type": "string"
          },
          "attributes": {}
        }
      },
      "JsonElement": {},
      "JsonObject": {
        "type": "object"
      },
      "LegalRepresentative": {
        "required": [
          "full_name"
        ],
        "type": "object",
        "properties": {
          "full_name": {
            "type": "string"
          },
          "role": {
            "type": [
              "null",
              "string"
            ]
          },
          "email": {
            "type": [
              "null",
              "string"
            ]
          },
          "phone_number": {
            "type": [
              "null",
              "string"
            ]
          },
          "identification_type": {
            "type": [
              "null",
              "string"
            ]
          },
          "identification_number": {
            "type": [
              "null",
              "string"
            ]
          },
          "identification_issue_date": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "MerchantAddress": {
        "type": "object",
        "properties": {
          "street": {
            "type": [
              "null",
              "string"
            ]
          },
          "number": {
            "type": [
              "null",
              "string"
            ]
          },
          "city": {
            "type": [
              "null",
              "string"
            ]
          },
          "state": {
            "type": [
              "null",
              "string"
            ]
          },
          "zip_code": {
            "type": [
              "null",
              "string"
            ]
          },
          "country": {
            "type": [
              "null",
              "string"
            ],
            "default": "COL"
          }
        }
      },
      "PayoutInformation": {
        "type": "object",
        "properties": {
          "currency": {
            "type": [
              "null",
              "string"
            ],
            "default": "COP"
          },
          "bank_name": {
            "type": [
              "null",
              "string"
            ]
          },
          "bank_country": {
            "type": [
              "null",
              "string"
            ],
            "default": "COL"
          },
          "bank_swift_code": {
            "type": [
              "null",
              "string"
            ]
          },
          "bank_account_type": {
            "type": [
              "null",
              "string"
            ]
          },
          "bank_account_number": {
            "type": [
              "null",
              "string"
            ]
          },
          "bank_account_holder_name": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "RegisterMerchantRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/RegisterMerchantRequestData"
          }
        }
      },
      "RegisterMerchantRequestAttributes": {
        "required": [
          "name",
          "alias",
          "email",
          "phone",
          "website",
          "logo",
          "primary_color",
          "support_text",
          "activity",
          "channel",
          "organization_id",
          "parent_id",
          "akua_merchant_id",
          "default_currency",
          "supported_currencies",
          "tax_id",
          "tax_id_type",
          "legal_name",
          "notes"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "alias": {
            "type": [
              "null",
              "string"
            ]
          },
          "email": {
            "type": "string"
          },
          "phone": {
            "type": [
              "null",
              "string"
            ]
          },
          "website": {
            "type": [
              "null",
              "string"
            ]
          },
          "logo": {
            "type": [
              "null",
              "string"
            ]
          },
          "primary_color": {
            "type": [
              "null",
              "string"
            ]
          },
          "support_text": {
            "type": [
              "null",
              "string"
            ]
          },
          "activity": {
            "type": [
              "null",
              "string"
            ]
          },
          "channel": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            }
          },
          "organization_id": {
            "type": [
              "null",
              "string"
            ]
          },
          "parent_id": {
            "type": [
              "null",
              "string"
            ]
          },
          "akua_merchant_id": {
            "type": [
              "null",
              "string"
            ]
          },
          "default_currency": {
            "type": [
              "null",
              "string"
            ]
          },
          "supported_currencies": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            }
          },
          "tax_id": {
            "type": "string"
          },
          "tax_id_type": {
            "type": [
              "null",
              "string"
            ]
          },
          "legal_name": {
            "type": [
              "null",
              "string"
            ]
          },
          "notes": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "RegisterMerchantRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/RegisterMerchantRequestAttributes"
          }
        }
      },
      "RegisterMerchantWebhookRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/RegisterMerchantWebhookRequestData"
          }
        }
      },
      "RegisterMerchantWebhookRequestAttributes": {
        "required": [
          "url",
          "description",
          "events",
          "headers"
        ],
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "events": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            }
          },
          "headers": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/JsonElement"
              }
            ]
          }
        }
      },
      "RegisterMerchantWebhookRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/RegisterMerchantWebhookRequestAttributes"
          }
        }
      },
      "SaveSectionRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/SaveSectionRequestData"
          }
        }
      },
      "SaveSectionRequestAttributes": {
        "required": [
          "name",
          "alias",
          "legal_name",
          "activity",
          "website",
          "phone",
          "person_type",
          "address",
          "location_address",
          "legal_representative",
          "payout_information"
        ],
        "type": "object",
        "properties": {
          "name": {
            "type": [
              "null",
              "string"
            ]
          },
          "alias": {
            "type": [
              "null",
              "string"
            ]
          },
          "legal_name": {
            "type": [
              "null",
              "string"
            ]
          },
          "activity": {
            "type": [
              "null",
              "string"
            ]
          },
          "website": {
            "type": [
              "null",
              "string"
            ]
          },
          "phone": {
            "type": [
              "null",
              "string"
            ]
          },
          "person_type": {
            "type": [
              "null",
              "string"
            ]
          },
          "address": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/MerchantAddress"
              }
            ]
          },
          "location_address": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/MerchantAddress"
              }
            ]
          },
          "legal_representative": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/LegalRepresentative"
              }
            ]
          },
          "payout_information": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/PayoutInformation"
              }
            ]
          }
        }
      },
      "SaveSectionRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/SaveSectionRequestAttributes"
          }
        }
      },
      "SectionReviewRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/SectionReviewRequestData"
          }
        }
      },
      "SectionReviewRequestAttributes": {
        "required": [
          "status",
          "note"
        ],
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "note": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "SectionReviewRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/SectionReviewRequestAttributes"
          }
        }
      },
      "SelfRegisterRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/SelfRegisterRequestData"
          }
        }
      },
      "SelfRegisterRequestAttributes": {
        "required": [
          "email",
          "password",
          "owner_full_name",
          "person_type",
          "name",
          "tax_id",
          "tax_id_type",
          "phone",
          "owner_identification_type",
          "owner_identification_number",
          "accepted_terms"
        ],
        "type": "object",
        "properties": {
          "email": {
            "type": "string"
          },
          "password": {
            "type": "string"
          },
          "owner_full_name": {
            "type": "string"
          },
          "person_type": {
            "type": [
              "null",
              "string"
            ]
          },
          "name": {
            "type": "string"
          },
          "tax_id": {
            "type": "string"
          },
          "tax_id_type": {
            "type": [
              "null",
              "string"
            ]
          },
          "phone": {
            "type": [
              "null",
              "string"
            ]
          },
          "owner_identification_type": {
            "type": [
              "null",
              "string"
            ]
          },
          "owner_identification_number": {
            "type": [
              "null",
              "string"
            ]
          },
          "accepted_terms": {
            "type": [
              "null",
              "boolean"
            ]
          }
        }
      },
      "SelfRegisterRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/SelfRegisterRequestAttributes"
          }
        }
      },
      "UpdateCatalogItemRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/UpdateCatalogItemRequestData"
          }
        }
      },
      "UpdateCatalogItemRequestAttributes": {
        "required": [
          "label",
          "parent_code",
          "sort_order",
          "active",
          "metadata"
        ],
        "type": "object",
        "properties": {
          "label": {
            "type": [
              "null",
              "string"
            ]
          },
          "parent_code": {
            "type": [
              "null",
              "string"
            ]
          },
          "sort_order": {
            "pattern": "^-?(?:0|[1-9]\\d*)$",
            "type": [
              "null",
              "integer",
              "string"
            ],
            "format": "int32"
          },
          "active": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "metadata": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/JsonElement"
              }
            ]
          }
        }
      },
      "UpdateCatalogItemRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/UpdateCatalogItemRequestAttributes"
          }
        }
      },
      "UpdateMerchantProfileRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/UpdateMerchantProfileRequestData"
          }
        }
      },
      "UpdateMerchantProfileRequestAttributes": {
        "required": [
          "alias",
          "phone",
          "website",
          "logo",
          "primary_color",
          "support_text",
          "activity",
          "akua_merchant_id",
          "legal_name",
          "notes"
        ],
        "type": "object",
        "properties": {
          "alias": {
            "type": [
              "null",
              "string"
            ]
          },
          "phone": {
            "type": [
              "null",
              "string"
            ]
          },
          "website": {
            "type": [
              "null",
              "string"
            ]
          },
          "logo": {
            "type": [
              "null",
              "string"
            ]
          },
          "primary_color": {
            "type": [
              "null",
              "string"
            ]
          },
          "support_text": {
            "type": [
              "null",
              "string"
            ]
          },
          "activity": {
            "type": [
              "null",
              "string"
            ]
          },
          "akua_merchant_id": {
            "type": [
              "null",
              "string"
            ]
          },
          "legal_name": {
            "type": [
              "null",
              "string"
            ]
          },
          "notes": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "UpdateMerchantProfileRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/UpdateMerchantProfileRequestAttributes"
          }
        }
      },
      "UpdateMerchantSettingsRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/UpdateMerchantSettingsRequestData"
          }
        }
      },
      "UpdateMerchantSettingsRequestAttributes": {
        "required": [
          "account_name",
          "legal_name",
          "display_name",
          "phone_type",
          "phone_country_code",
          "phone",
          "contact_email",
          "chargebacks_email",
          "billing_email",
          "transactions_email",
          "tickets_email"
        ],
        "type": "object",
        "properties": {
          "account_name": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "legal_name": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "display_name": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "phone_type": {
            "type": [
              "null",
              "string"
            ]
          },
          "phone_country_code": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "phone": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "contact_email": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "chargebacks_email": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "billing_email": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "transactions_email": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "tickets_email": {
            "$ref": "#/components/schemas/JsonElement"
          }
        }
      },
      "UpdateMerchantSettingsRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/UpdateMerchantSettingsRequestAttributes"
          }
        }
      },
      "UpdateMerchantWebhookConfigRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/UpdateMerchantWebhookConfigRequestData"
          }
        }
      },
      "UpdateMerchantWebhookConfigRequestAttributes": {
        "required": [
          "url",
          "description",
          "events",
          "headers",
          "status"
        ],
        "type": "object",
        "properties": {
          "url": {
            "type": [
              "null",
              "string"
            ]
          },
          "description": {
            "type": [
              "null",
              "string"
            ]
          },
          "events": {
            "type": [
              "null",
              "array"
            ],
            "items": {
              "type": "string"
            }
          },
          "headers": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/JsonElement"
              }
            ]
          },
          "status": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "UpdateMerchantWebhookConfigRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/UpdateMerchantWebhookConfigRequestAttributes"
          }
        }
      },
      "WebCheckoutLogoUploadRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/WebCheckoutLogoUploadRequestData"
              }
            ]
          },
          "content_type": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "WebCheckoutLogoUploadRequestAttributes": {
        "required": [
          "content_type"
        ],
        "type": "object",
        "properties": {
          "content_type": {
            "type": [
              "null",
              "string"
            ]
          }
        }
      },
      "WebCheckoutLogoUploadRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/WebCheckoutLogoUploadRequestAttributes"
          }
        }
      },
      "WebCheckoutRequest": {
        "required": [
          "data"
        ],
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/WebCheckoutRequestData"
          }
        }
      },
      "WebCheckoutRequestAttributes": {
        "required": [
          "name",
          "status",
          "subdomain",
          "default_currency",
          "default_language",
          "cash_expiration",
          "retry_button_in_email",
          "show_currency_conversion",
          "allow_checkout_retries",
          "response_url",
          "confirmation_url",
          "primary_color",
          "support_text",
          "logo_key"
        ],
        "type": "object",
        "properties": {
          "name": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "status": {
            "type": [
              "null",
              "string"
            ]
          },
          "subdomain": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "default_currency": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "default_language": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "cash_expiration": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "retry_button_in_email": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "show_currency_conversion": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "allow_checkout_retries": {
            "type": [
              "null",
              "boolean"
            ]
          },
          "response_url": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "confirmation_url": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "primary_color": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "support_text": {
            "$ref": "#/components/schemas/JsonElement"
          },
          "logo_key": {
            "$ref": "#/components/schemas/JsonElement"
          }
        }
      },
      "WebCheckoutRequestData": {
        "required": [
          "attributes"
        ],
        "type": "object",
        "properties": {
          "attributes": {
            "$ref": "#/components/schemas/WebCheckoutRequestAttributes"
          }
        }
      }
    },
    "securitySchemes": {
      "Bearer": {
        "type": "http",
        "description": "JWT emitido por Keycloak (realm `payment-engine`).",
        "scheme": "bearer",
        "bearerFormat": "JWT"
      }
    }
  },
  "tags": [
    {
      "name": "Onboarding",
      "description": "Auto-registro del comercio y su asistente de vinculación: datos por sección, documentos y envío a revisión."
    },
    {
      "name": "KYC",
      "description": "Información de conocimiento del cliente dirigida por esquema: esquema y reglas, documento por sección, actualizaciones posteriores a la aprobación, diff e historial."
    },
    {
      "name": "Catálogos",
      "description": "Listas administrables que usa el formulario KYC (actividad económica, ocupación, nacionalidad, tipos de documento…)."
    },
    {
      "name": "Comercios",
      "description": "Registro y perfil del propio comercio."
    },
    {
      "name": "Links de pago",
      "description": "Links de cobro del comercio: crear, consultar, revocar y reactivar."
    },
    {
      "name": "Configuración del comercio",
      "description": "Opciones de la cuenta, llaves de API (con rotación del secreto) y lista blanca de IP del comercio."
    },
    {
      "name": "Web checkouts",
      "description": "Checkouts web del comercio (N por comercio): moneda, idioma, expiración, URLs de respuesta y confirmación, subdominio y personalización (logo, color)."
    },
    {
      "name": "Webhooks del comercio",
      "description": "Destinos a los que el motor notifica los eventos de pago del comercio."
    },
    {
      "name": "Admin · Comercios",
      "description": "Alta, edición y consulta de cualquier comercio por el administrador (`bank-admin`)."
    },
    {
      "name": "Admin · Verificación",
      "description": "Decisiones sobre la verificación (iniciar revisión, pedir cambios, aprobar, rechazar, suspender…), secciones y documentos."
    },
    {
      "name": "Admin · Akua",
      "description": "Registro opcional del comercio en Akua y sincronización de los cambios aprobados después."
    },
    {
      "name": "Admin · KYC",
      "description": "Lectura y corrección del KYC de un comercio y definición de las reglas por campo."
    },
    {
      "name": "Admin · Catálogos",
      "description": "Alta y edición de ítems de catálogo (no hay borrado: se desactiva) y su historial."
    },
    {
      "name": "Admin · Cobros",
      "description": "Consulta de los links de pago de cualquier comercio."
    },
    {
      "name": "Webhooks entrantes",
      "description": "Notificaciones que envían Akua y Crezcamos-PSE al motor. Se autentican con firma, no con token."
    },
    {
      "name": "Sistema",
      "description": "Salud del servicio."
    }
  ]
}
