{
    "openapi": "3.1.0",
    "info": {
        "title": "Voilatier API",
        "description": "API REST de Voilatier. Autenticación por API key (Bearer). Idempotencia obligatoria en POST/PATCH.",
        "contact": {
            "name": "Voilatier API",
            "email": "developers@voilatier.com"
        },
        "version": "v1"
    },
    "servers": [
        {
            "url": "https://dash.voilatier.com",
            "description": "Production"
        }
    ],
    "paths": {
        "/api/v1/accounts/{customerId}/tier": {
            "get": {
                "tags": [
                    "Tiers"
                ],
                "summary": "Read a customer or account current tier + qualification progress",
                "operationId": "accounts.tier",
                "parameters": [
                    {
                        "name": "customerId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Tier + progress info"
                    },
                    "404": {
                        "description": "Customer not found in this tenant"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/ai/campaign/draft": {
            "post": {
                "tags": [
                    "AI"
                ],
                "summary": "Translate a natural-language prompt into a campaign draft",
                "description": "Wraps the CampaignNlTranslator. Creates a campaign in draft state and returns the draft for review in the panel.",
                "operationId": "ai.campaign.draft",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "prompt"
                                ],
                                "properties": {
                                    "prompt": {
                                        "type": "string",
                                        "example": "Mandar WhatsApp a clientes VIP con 20% off este fin de semana",
                                        "maxLength": 2000
                                    },
                                    "locale": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "example": "es"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Campaign draft created"
                    },
                    "422": {
                        "description": "Validation failed / translator rejected output"
                    },
                    "502": {
                        "description": "Upstream AI error"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/categories": {
            "get": {
                "tags": [
                    "Categories"
                ],
                "summary": "List the tenant transaction categories",
                "description": "Returns the active transaction categories (slug + name) the POS can send as `category_slug` when ingesting a transaction.",
                "operationId": "categories.index",
                "parameters": [
                    {
                        "name": "include_inactive",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "boolean"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Transaction categories"
                    },
                    "401": {
                        "description": "Invalid or missing API key"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/customers/{customerId}/benefits": {
            "get": {
                "tags": [
                    "Customers"
                ],
                "summary": "Resolve the tier benefits payload for a customer",
                "operationId": "customers.benefits",
                "parameters": [
                    {
                        "name": "customerId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Benefit payload"
                    },
                    "404": {
                        "description": "Customer not found"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/customers/by-external-id": {
            "post": {
                "tags": [
                    "Customers"
                ],
                "summary": "Upsert customer by ERP external_id",
                "description": "Returns 200 with the existing customer or 201 with a newly created one. Tenant scoped via API key.",
                "operationId": "customers.byExternalId",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "external_id"
                                ],
                                "properties": {
                                    "external_id": {
                                        "type": "string",
                                        "maxLength": 64
                                    },
                                    "defaults": {
                                        "description": "Used only when creating",
                                        "properties": {
                                            "type": {
                                                "type": "string",
                                                "enum": [
                                                    "individual",
                                                    "account"
                                                ]
                                            },
                                            "first_name": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ]
                                            },
                                            "last_name": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ]
                                            },
                                            "legal_name": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ]
                                            },
                                            "tax_id": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ]
                                            },
                                            "phone": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ]
                                            },
                                            "email": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ],
                                                "format": "email"
                                            },
                                            "language": {
                                                "type": [
                                                    "string",
                                                    "null"
                                                ]
                                            }
                                        },
                                        "type": "object"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Existing customer"
                    },
                    "201": {
                        "description": "Customer created"
                    },
                    "422": {
                        "description": "Validation failed"
                    },
                    "401": {
                        "description": "Invalid or missing API key"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/customers/{customerId}": {
            "get": {
                "tags": [
                    "Customers"
                ],
                "summary": "Fetch a single customer by id",
                "operationId": "customers.show",
                "parameters": [
                    {
                        "name": "customerId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Customer payload"
                    },
                    "404": {
                        "description": "Customer not found in this tenant"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/customers": {
            "post": {
                "tags": [
                    "Customers"
                ],
                "summary": "Create a customer (individual or B2B account)",
                "operationId": "customers.store",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "properties": {
                                    "type": {
                                        "type": "string",
                                        "enum": [
                                            "individual",
                                            "account"
                                        ]
                                    },
                                    "first_name": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "last_name": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "legal_name": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "tax_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "phone": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "email": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "email"
                                    },
                                    "language": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Customer created"
                    },
                    "409": {
                        "description": "Customer with same phone or email already exists"
                    },
                    "422": {
                        "description": "Validation failed"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/customers/{customerId}/tier": {
            "get": {
                "tags": [
                    "Customers"
                ],
                "summary": "Effective tier (threshold + active grants) for the customer",
                "operationId": "customers.tier",
                "parameters": [
                    {
                        "name": "customerId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Effective tier payload"
                    },
                    "404": {
                        "description": "Customer not found in this tenant"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/customers/{customerId}/points-balance": {
            "get": {
                "tags": [
                    "Customers"
                ],
                "summary": "Lightweight points snapshot for the customer",
                "operationId": "customers.pointsBalance",
                "parameters": [
                    {
                        "name": "customerId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "If-None-Match",
                        "in": "header",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Snapshot"
                    },
                    "304": {
                        "description": "Not modified — caller already has the latest snapshot"
                    },
                    "404": {
                        "description": "Customer not found in this tenant"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/customers/{customerId}/redemption-options": {
            "get": {
                "tags": [
                    "Redemptions"
                ],
                "summary": "Rewards the customer can currently redeem",
                "operationId": "customers.redemptionOptions",
                "parameters": [
                    {
                        "name": "customerId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Reward catalog with eligibility"
                    },
                    "404": {
                        "description": "Customer not found in this tenant"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/customers/{customerId}/schedules": {
            "get": {
                "tags": [
                    "Customers"
                ],
                "summary": "List the customer's schedules grouped by status (open / met / missed)",
                "operationId": "customers.schedules",
                "parameters": [
                    {
                        "name": "customerId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "template_slug",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Schedules grouped by bucket"
                    },
                    "404": {
                        "description": "Customer not found"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/customers/{customerId}/stamps": {
            "get": {
                "tags": [
                    "Customers"
                ],
                "summary": "List every stamp program the customer participates in with current counts",
                "operationId": "customers.stamps",
                "parameters": [
                    {
                        "name": "customerId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Stamp programs + balances"
                    },
                    "404": {
                        "description": "Customer not found"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/journeys/{journeyId}/enroll": {
            "post": {
                "tags": [
                    "Journeys"
                ],
                "summary": "Enroll a customer into a journey",
                "description": "Returns 201 on new enrolment, 200 when the customer already has an active enrolment in this journey (policy=once).",
                "operationId": "journeys.enroll",
                "parameters": [
                    {
                        "name": "journeyId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "customer_id"
                                ],
                                "properties": {
                                    "customer_id": {
                                        "type": "integer",
                                        "example": 1
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Enrolment created"
                    },
                    "200": {
                        "description": "Existing active enrolment returned"
                    },
                    "422": {
                        "description": "Journey not active OR validation failed"
                    },
                    "404": {
                        "description": "Journey or customer not found"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/customers/{customerId}/points-adjustment": {
            "post": {
                "tags": [
                    "Points"
                ],
                "summary": "Manually credit or debit a customer's points",
                "operationId": "customers.points.adjust",
                "parameters": [
                    {
                        "name": "customerId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "amount",
                                    "reason"
                                ],
                                "properties": {
                                    "amount": {
                                        "description": "Positive to credit, negative to debit. Cannot be 0.",
                                        "type": "integer",
                                        "example": 250
                                    },
                                    "reason": {
                                        "type": "string",
                                        "example": "Goodwill credit — ERP ticket #4821"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Adjustment applied"
                    },
                    "404": {
                        "description": "Customer not found in this tenant"
                    },
                    "422": {
                        "description": "Validation failed"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/products": {
            "get": {
                "tags": [
                    "Products"
                ],
                "summary": "List the tenant product catalog",
                "operationId": "products.index",
                "parameters": [
                    {
                        "name": "include_inactive",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "boolean"
                        }
                    },
                    {
                        "name": "category_slug",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Product catalog"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            },
            "post": {
                "tags": [
                    "Products"
                ],
                "summary": "Create or update a product (upsert by SKU)",
                "operationId": "products.upsert",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "sku",
                                    "name"
                                ],
                                "properties": {
                                    "sku": {
                                        "type": "string",
                                        "example": "ACURA-MDX"
                                    },
                                    "name": {
                                        "type": "string",
                                        "example": "Acura MDX 2026"
                                    },
                                    "description": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "category_slug": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "example": "venta"
                                    },
                                    "unit_price": {
                                        "type": [
                                            "number",
                                            "null"
                                        ],
                                        "example": 70000
                                    },
                                    "currency": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "example": "USD"
                                    },
                                    "attributes": {
                                        "type": [
                                            "object",
                                            "null"
                                        ],
                                        "example": {
                                            "brand": "Acura",
                                            "segment": "luxury"
                                        }
                                    },
                                    "is_active": {
                                        "type": [
                                            "boolean",
                                            "null"
                                        ],
                                        "example": true
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Existing product updated"
                    },
                    "201": {
                        "description": "New product created"
                    },
                    "422": {
                        "description": "Validation failed"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/redemptions": {
            "post": {
                "tags": [
                    "Redemptions"
                ],
                "summary": "Create a redemption (debit points + reserve reward)",
                "description": "Wraps the RedemptionEngine. Returns 201 with the new redemption + a short code the staff can scan to fulfill.",
                "operationId": "redemptions.store",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "customer_id",
                                    "reward_id"
                                ],
                                "properties": {
                                    "customer_id": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "reward_id": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "store_id": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ]
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Redemption created"
                    },
                    "422": {
                        "description": "Validation failed / inactive reward / insufficient points"
                    },
                    "401": {
                        "description": "Invalid or missing API key"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/redemptions/{id}/fulfill": {
            "post": {
                "tags": [
                    "Redemptions"
                ],
                "summary": "Fulfill a pending redemption (mark the reward delivered)",
                "operationId": "redemptions.fulfill",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Redemption fulfilled"
                    },
                    "404": {
                        "description": "No such redemption in this tenant"
                    },
                    "422": {
                        "description": "Redemption is not pending"
                    },
                    "401": {
                        "description": "Invalid or missing API key"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/redemptions/preview": {
            "post": {
                "tags": [
                    "Redemptions"
                ],
                "summary": "Dry-run a redemption — no side effects",
                "operationId": "redemptions.preview",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "customer_id",
                                    "reward_id"
                                ],
                                "properties": {
                                    "customer_id": {
                                        "type": "integer"
                                    },
                                    "reward_id": {
                                        "type": "integer"
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Preview payload"
                    },
                    "422": {
                        "description": "Validation failed / unknown customer or reward"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/rewards": {
            "get": {
                "tags": [
                    "Rewards"
                ],
                "summary": "List the tenant reward catalog",
                "operationId": "rewards.index",
                "parameters": [
                    {
                        "name": "include_inactive",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "boolean"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Reward catalog"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/tiers/{customerId}/qualification": {
            "patch": {
                "tags": [
                    "Tiers"
                ],
                "summary": "Force tier re-qualification for one customer",
                "description": "Idempotent. Recomputes the qualifying metric and persists the tier change if any. Useful when an out-of-band correction lands.",
                "operationId": "tiers.qualification.update",
                "parameters": [
                    {
                        "name": "customerId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Tier re-qualified (may be a no-op)"
                    },
                    "404": {
                        "description": "Customer not found"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/transactions/by-erp-doc": {
            "post": {
                "tags": [
                    "Transactions"
                ],
                "summary": "Ingest a transaction keyed by an ERP document number (idempotent)",
                "operationId": "transactions.byErpDoc",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "erp_document_number",
                                    "amount",
                                    "currency"
                                ],
                                "properties": {
                                    "erp_document_number": {
                                        "type": "string",
                                        "maxLength": 120
                                    },
                                    "erp_document_type": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 32
                                    },
                                    "customer_external_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "maxLength": 64
                                    },
                                    "customer_id": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ]
                                    },
                                    "customer_phone": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "store_id": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ]
                                    },
                                    "category_slug": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "amount": {
                                        "type": "number",
                                        "format": "float"
                                    },
                                    "currency": {
                                        "type": "string",
                                        "example": "USD"
                                    },
                                    "occurred_at": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "date-time"
                                    },
                                    "items": {
                                        "type": [
                                            "array",
                                            "null"
                                        ],
                                        "items": {
                                            "type": "object"
                                        }
                                    },
                                    "metadata": {
                                        "type": [
                                            "object",
                                            "null"
                                        ]
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Existing transaction (duplicate document number)"
                    },
                    "201": {
                        "description": "Transaction created"
                    },
                    "422": {
                        "description": "Validation failed"
                    },
                    "401": {
                        "description": "Invalid or missing API key"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/transactions": {
            "post": {
                "tags": [
                    "Transactions"
                ],
                "summary": "Ingest a transaction from the merchant POS / e-commerce",
                "description": "Inserts a transaction, runs the loyalty cascade (line items → bundles → schedules → stamps → points → webhooks), and returns the enriched payload so the cashier can see the loyalty effect immediately.",
                "operationId": "transactions.store",
                "parameters": [
                    {
                        "name": "Idempotency-Key",
                        "in": "header",
                        "required": true,
                        "schema": {
                            "type": "string"
                        }
                    }
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "amount",
                                    "currency"
                                ],
                                "properties": {
                                    "customer_id": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ]
                                    },
                                    "customer_phone": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "store_id": {
                                        "type": [
                                            "integer",
                                            "null"
                                        ]
                                    },
                                    "category_slug": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "amount": {
                                        "type": "number",
                                        "format": "float",
                                        "example": 52.4
                                    },
                                    "currency": {
                                        "type": "string",
                                        "example": "USD"
                                    },
                                    "external_id": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    },
                                    "occurred_at": {
                                        "type": [
                                            "string",
                                            "null"
                                        ],
                                        "format": "date-time"
                                    },
                                    "items": {
                                        "type": [
                                            "array",
                                            "null"
                                        ],
                                        "items": {
                                            "type": "object"
                                        }
                                    },
                                    "metadata": {
                                        "type": [
                                            "object",
                                            "null"
                                        ]
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Transaction created and enriched"
                    },
                    "422": {
                        "description": "Validation failed"
                    },
                    "401": {
                        "description": "Invalid or missing API key"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/transactions/{id}": {
            "get": {
                "tags": [
                    "Transactions"
                ],
                "summary": "Fetch a single transaction by id",
                "operationId": "transactions.show",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Transaction payload"
                    },
                    "404": {
                        "description": "Transaction not found in this tenant"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/customers/{customerId}/transactions": {
            "get": {
                "tags": [
                    "Transactions"
                ],
                "summary": "Paginated transaction history for a customer",
                "operationId": "customers.transactions.index",
                "parameters": [
                    {
                        "name": "customerId",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "required": false,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Paginated transactions"
                    },
                    "404": {
                        "description": "Customer not found in this tenant"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/webhooks": {
            "get": {
                "tags": [
                    "Webhooks · gestión"
                ],
                "summary": "List webhook endpoints",
                "operationId": "webhooks.index",
                "responses": {
                    "200": {
                        "description": "Endpoints"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            },
            "post": {
                "tags": [
                    "Webhooks · gestión"
                ],
                "summary": "Register a webhook endpoint",
                "operationId": "webhooks.store",
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "required": [
                                    "url",
                                    "events"
                                ],
                                "properties": {
                                    "url": {
                                        "type": "string",
                                        "format": "uri",
                                        "example": "https://erp.example.com/voilatier/hook"
                                    },
                                    "events": {
                                        "type": "array",
                                        "items": {
                                            "type": "string"
                                        },
                                        "example": [
                                            "transaction.created",
                                            "tier.upgraded"
                                        ]
                                    },
                                    "description": {
                                        "type": [
                                            "string",
                                            "null"
                                        ]
                                    }
                                },
                                "type": "object"
                            }
                        }
                    }
                },
                "responses": {
                    "201": {
                        "description": "Created (secret returned once)"
                    },
                    "422": {
                        "description": "Validation failed"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        },
        "/api/v1/webhooks/{id}": {
            "delete": {
                "tags": [
                    "Webhooks · gestión"
                ],
                "summary": "Delete a webhook endpoint",
                "operationId": "webhooks.destroy",
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "schema": {
                            "type": "integer"
                        }
                    }
                ],
                "responses": {
                    "204": {
                        "description": "Deleted"
                    },
                    "404": {
                        "description": "Endpoint not found in this tenant"
                    }
                },
                "security": [
                    {
                        "bearerAuth": []
                    }
                ]
            }
        }
    },
    "components": {
        "schemas": {
            "WhEnvelope": {
                "description": "Sobre común a TODOS los webhooks. `data` cambia según el evento.",
                "properties": {
                    "id": {
                        "description": "Id único de la entrega — deduplicá por esto.",
                        "type": "string",
                        "format": "uuid",
                        "example": "019e74a3-1c2d-7f00-8a1b-3c4d5e6f7a8b"
                    },
                    "event": {
                        "type": "string",
                        "example": "tier.upgraded"
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "company_id": {
                        "type": "integer",
                        "example": 3
                    },
                    "data": {
                        "type": "object"
                    }
                },
                "type": "object"
            },
            "WhCustomer": {
                "properties": {
                    "id": {
                        "type": "integer",
                        "example": 60
                    },
                    "type": {
                        "type": "string",
                        "example": "individual"
                    },
                    "display_name": {
                        "type": "string",
                        "example": "Marcel Auto"
                    },
                    "first_name": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "last_name": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "legal_name": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "tax_id": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "external_id": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "phone": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "email": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "example": "cliente@correo.com"
                    },
                    "tier_slug": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "example": "oro"
                    },
                    "points_balance": {
                        "type": "integer",
                        "example": 108
                    },
                    "created_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "anonymized_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    }
                },
                "type": "object"
            },
            "WhTransaction": {
                "properties": {
                    "id": {
                        "type": "integer",
                        "example": 222
                    },
                    "external_id": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "customer_id": {
                        "type": [
                            "integer",
                            "null"
                        ],
                        "example": 60
                    },
                    "store_id": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    },
                    "category_id": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    },
                    "amount": {
                        "type": "string",
                        "example": "60.00"
                    },
                    "currency": {
                        "type": "string",
                        "example": "USD"
                    },
                    "occurred_at": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "metadata": {
                        "type": [
                            "object",
                            "null"
                        ]
                    },
                    "line_items": {
                        "type": "array",
                        "items": {
                            "properties": {
                                "product_id": {
                                    "type": [
                                        "integer",
                                        "null"
                                    ]
                                },
                                "sku": {
                                    "type": [
                                        "string",
                                        "null"
                                    ]
                                },
                                "name": {
                                    "type": [
                                        "string",
                                        "null"
                                    ]
                                },
                                "category_id": {
                                    "type": [
                                        "integer",
                                        "null"
                                    ]
                                },
                                "quantity": {
                                    "type": "number"
                                },
                                "unit_price": {
                                    "type": [
                                        "number",
                                        "null"
                                    ]
                                },
                                "total": {
                                    "type": [
                                        "number",
                                        "null"
                                    ]
                                }
                            },
                            "type": "object"
                        }
                    }
                },
                "type": "object"
            },
            "WhPointMovement": {
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "customer_id": {
                        "type": "integer"
                    },
                    "type": {
                        "type": "string",
                        "example": "earn"
                    },
                    "amount": {
                        "description": "Positivo gana, negativo descuenta.",
                        "type": "integer",
                        "example": 60
                    },
                    "balance_before": {
                        "type": "integer"
                    },
                    "balance_after": {
                        "type": "integer"
                    },
                    "reference_type": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "reference_id": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    },
                    "rule_id": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    },
                    "store_id": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    },
                    "reason": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "type": "object"
            },
            "WhStampMovement": {
                "properties": {
                    "id": {
                        "type": "string",
                        "format": "uuid"
                    },
                    "customer_id": {
                        "type": "integer"
                    },
                    "program_id": {
                        "type": "integer"
                    },
                    "program_slug": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "program_name": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "count_delta": {
                        "type": "integer",
                        "example": 1
                    },
                    "balance_after": {
                        "type": "integer",
                        "example": 3
                    },
                    "reward_earned": {
                        "type": "boolean"
                    },
                    "reference_type": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "reference_id": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    },
                    "reason": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                },
                "type": "object"
            },
            "WhSchedule": {
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "customer_id": {
                        "type": "integer"
                    },
                    "template_id": {
                        "type": "integer"
                    },
                    "template_slug": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "template_name": {
                        "type": [
                            "string",
                            "null"
                        ]
                    },
                    "sequence_number": {
                        "type": "integer"
                    },
                    "due_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "window_before_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "window_after_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "status": {
                        "type": "string",
                        "example": "met_on_time"
                    },
                    "met_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "source_transaction_id": {
                        "type": [
                            "integer",
                            "null"
                        ]
                    }
                },
                "type": "object"
            },
            "WhTierRef": {
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "slug": {
                        "type": "string",
                        "example": "oro"
                    },
                    "name": {
                        "type": "string",
                        "example": "Oro"
                    }
                },
                "type": [
                    "object",
                    "null"
                ]
            }
        },
        "securitySchemes": {
            "bearerAuth": {
                "type": "http",
                "description": "Authorization: Bearer vlt_live_xxx. POST/PATCH también requieren cabecera Idempotency-Key.",
                "bearerFormat": "Voilatier API Key (vlt_live_… / vlt_test_…)",
                "scheme": "bearer"
            }
        }
    },
    "tags": [
        {
            "name": "Tiers",
            "description": "Tiers"
        },
        {
            "name": "AI",
            "description": "AI"
        },
        {
            "name": "Categories",
            "description": "Categories"
        },
        {
            "name": "Customers",
            "description": "Customers"
        },
        {
            "name": "Redemptions",
            "description": "Redemptions"
        },
        {
            "name": "Journeys",
            "description": "Journeys"
        },
        {
            "name": "Points",
            "description": "Points"
        },
        {
            "name": "Products",
            "description": "Products"
        },
        {
            "name": "Rewards",
            "description": "Rewards"
        },
        {
            "name": "Transactions",
            "description": "Transactions"
        },
        {
            "name": "Webhooks · gestión",
            "description": "Webhooks · gestión"
        }
    ],
    "webhooks": {
        "customer.created": {
            "post": {
                "summary": "Cliente creado",
                "description": "OpenAPI definitions for OUTBOUND webhooks (Voilatier → merchant endpoint).\n\nNo executable code — only annotations so every event renders in Swagger UI\n(`/api/documentation`) as a definition, with no need to fire one to learn\nits shape. Mirrors the dispatch sites + `App\\Services\\Webhooks\\Payloads\\*`.\nRequires OpenAPI 3.1 (`webhooks` keyword), set in config/l5-swagger.php.\n\nEach reusable object is its own `#[OA\\Schema]` class; the webhooks live on\n{@see WebhookDocs} and each overrides only `data` via `allOf`.",
                "operationId": "wh_customer_created",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WhEnvelope"
                                    },
                                    {
                                        "properties": {
                                            "data": {
                                                "properties": {
                                                    "customer": {
                                                        "$ref": "#/components/schemas/WhCustomer"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        },
        "customer.created_via_api": {
            "post": {
                "summary": "Cliente creado vía API",
                "operationId": "wh_customer_created_via_api",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WhEnvelope"
                                    },
                                    {
                                        "properties": {
                                            "data": {
                                                "properties": {
                                                    "customer": {
                                                        "$ref": "#/components/schemas/WhCustomer"
                                                    },
                                                    "via": {
                                                        "type": "string",
                                                        "example": "api"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        },
        "transaction.created": {
            "post": {
                "summary": "Transacción creada",
                "operationId": "wh_transaction_created",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WhEnvelope"
                                    },
                                    {
                                        "properties": {
                                            "data": {
                                                "properties": {
                                                    "transaction": {
                                                        "$ref": "#/components/schemas/WhTransaction"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        },
        "points.earned": {
            "post": {
                "summary": "Puntos acumulados",
                "operationId": "wh_points_earned",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WhEnvelope"
                                    },
                                    {
                                        "properties": {
                                            "data": {
                                                "properties": {
                                                    "movement": {
                                                        "$ref": "#/components/schemas/WhPointMovement"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        },
        "points.redeemed": {
            "post": {
                "summary": "Puntos canjeados (movimiento de ledger)",
                "operationId": "wh_points_redeemed",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WhEnvelope"
                                    },
                                    {
                                        "properties": {
                                            "data": {
                                                "properties": {
                                                    "movement": {
                                                        "$ref": "#/components/schemas/WhPointMovement"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        },
        "points.expired": {
            "post": {
                "summary": "Puntos expirados",
                "operationId": "wh_points_expired",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WhEnvelope"
                                    },
                                    {
                                        "properties": {
                                            "data": {
                                                "properties": {
                                                    "customer_id": {
                                                        "type": "integer"
                                                    },
                                                    "amount": {
                                                        "type": "integer"
                                                    },
                                                    "balance_after": {
                                                        "type": "integer"
                                                    },
                                                    "cutoff": {
                                                        "type": "string",
                                                        "format": "date-time"
                                                    },
                                                    "loyalty_program_id": {
                                                        "type": "integer"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        },
        "redemption.completed": {
            "post": {
                "summary": "Canje completado",
                "operationId": "wh_redemption_completed",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WhEnvelope"
                                    },
                                    {
                                        "properties": {
                                            "data": {
                                                "properties": {
                                                    "redemption": {
                                                        "properties": {
                                                            "id": {
                                                                "type": "integer"
                                                            },
                                                            "code": {
                                                                "type": "string",
                                                                "example": "S89QF7A6"
                                                            },
                                                            "customer_id": {
                                                                "type": "integer"
                                                            },
                                                            "reward_id": {
                                                                "type": "integer"
                                                            },
                                                            "store_id": {
                                                                "type": [
                                                                    "integer",
                                                                    "null"
                                                                ]
                                                            },
                                                            "points_debited": {
                                                                "type": "integer",
                                                                "example": 200
                                                            },
                                                            "status": {
                                                                "type": "string",
                                                                "example": "pending"
                                                            },
                                                            "redeemed_at": {
                                                                "type": "string",
                                                                "format": "date-time"
                                                            }
                                                        },
                                                        "type": "object"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        },
        "tier.changed": {
            "post": {
                "summary": "Nivel cambió (genérico)",
                "operationId": "wh_tier_changed",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WhEnvelope"
                                    },
                                    {
                                        "properties": {
                                            "data": {
                                                "properties": {
                                                    "customer": {
                                                        "$ref": "#/components/schemas/WhCustomer"
                                                    },
                                                    "previous_tier": {
                                                        "$ref": "#/components/schemas/WhTierRef"
                                                    },
                                                    "new_tier": {
                                                        "$ref": "#/components/schemas/WhTierRef"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        },
        "tier.upgraded": {
            "post": {
                "summary": "Nivel ascendió",
                "operationId": "wh_tier_upgraded",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WhEnvelope"
                                    },
                                    {
                                        "properties": {
                                            "data": {
                                                "properties": {
                                                    "customer": {
                                                        "$ref": "#/components/schemas/WhCustomer"
                                                    },
                                                    "previous_tier": {
                                                        "$ref": "#/components/schemas/WhTierRef"
                                                    },
                                                    "new_tier": {
                                                        "$ref": "#/components/schemas/WhTierRef"
                                                    },
                                                    "direction": {
                                                        "type": "string",
                                                        "example": "up"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        },
        "tier.downgraded": {
            "post": {
                "summary": "Nivel descendió",
                "operationId": "wh_tier_downgraded",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WhEnvelope"
                                    },
                                    {
                                        "properties": {
                                            "data": {
                                                "properties": {
                                                    "customer": {
                                                        "$ref": "#/components/schemas/WhCustomer"
                                                    },
                                                    "previous_tier": {
                                                        "$ref": "#/components/schemas/WhTierRef"
                                                    },
                                                    "new_tier": {
                                                        "$ref": "#/components/schemas/WhTierRef"
                                                    },
                                                    "direction": {
                                                        "type": "string",
                                                        "example": "down"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        },
        "tier.granted": {
            "post": {
                "summary": "Nivel otorgado (por regla/manual)",
                "operationId": "wh_tier_granted",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WhEnvelope"
                                    },
                                    {
                                        "properties": {
                                            "data": {
                                                "properties": {
                                                    "customer_id": {
                                                        "type": "integer"
                                                    },
                                                    "tier": {
                                                        "$ref": "#/components/schemas/WhTierRef"
                                                    },
                                                    "granted_at": {
                                                        "type": "string",
                                                        "format": "date-time"
                                                    },
                                                    "expires_at": {
                                                        "type": [
                                                            "string",
                                                            "null"
                                                        ],
                                                        "format": "date-time"
                                                    },
                                                    "reason": {
                                                        "type": "string",
                                                        "example": "vehicle_purchase"
                                                    },
                                                    "source": {
                                                        "properties": {
                                                            "type": {
                                                                "type": "string",
                                                                "example": "rule"
                                                            },
                                                            "rule_id": {
                                                                "type": "integer"
                                                            },
                                                            "rule_name": {
                                                                "type": "string"
                                                            },
                                                            "transaction_id": {
                                                                "type": [
                                                                    "integer",
                                                                    "null"
                                                                ]
                                                            }
                                                        },
                                                        "type": "object"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        },
        "schedule.met": {
            "post": {
                "summary": "Cronograma cumplido",
                "operationId": "wh_schedule_met",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WhEnvelope"
                                    },
                                    {
                                        "properties": {
                                            "data": {
                                                "properties": {
                                                    "schedule": {
                                                        "$ref": "#/components/schemas/WhSchedule"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        },
        "schedule.missed": {
            "post": {
                "summary": "Cronograma incumplido",
                "operationId": "wh_schedule_missed",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WhEnvelope"
                                    },
                                    {
                                        "properties": {
                                            "data": {
                                                "properties": {
                                                    "schedule": {
                                                        "$ref": "#/components/schemas/WhSchedule"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        },
        "stamp.earned": {
            "post": {
                "summary": "Sello acumulado",
                "operationId": "wh_stamp_earned",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WhEnvelope"
                                    },
                                    {
                                        "properties": {
                                            "data": {
                                                "properties": {
                                                    "movement": {
                                                        "$ref": "#/components/schemas/WhStampMovement"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        },
        "stamp.reward_earned": {
            "post": {
                "summary": "Recompensa de sellos completada",
                "operationId": "wh_stamp_reward_earned",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "allOf": [
                                    {
                                        "$ref": "#/components/schemas/WhEnvelope"
                                    },
                                    {
                                        "properties": {
                                            "data": {
                                                "properties": {
                                                    "movement": {
                                                        "$ref": "#/components/schemas/WhStampMovement"
                                                    }
                                                },
                                                "type": "object"
                                            }
                                        },
                                        "type": "object"
                                    }
                                ]
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        },
        "test.ping": {
            "post": {
                "summary": "Ping de prueba (botón \"Probar envío\")",
                "operationId": "wh_test_ping",
                "requestBody": {
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WhEnvelope"
                            }
                        }
                    }
                },
                "responses": {
                    "200": {
                        "description": "Respondé 2xx."
                    }
                }
            }
        }
    }
}