{
    "openapi": "3.1.0",
    "info": {
        "title": "TourismRevenue Integrator API",
        "version": "1.0.0",
        "summary": "Issue fiscal invoices and account for the Tourism Development Contribution from the software a business already runs.",
        "description": "Issue fiscal invoices and account for the Tourism Development Contribution straight from the software a business already runs.\n\nAuthentication: Authorization: Bearer sk_live_… (or sk_test_… for the sandbox). An integrator key must also name the business it is acting for in X-Operator-Code, and hold that business's active grant.\n\nMoney is kobo integers, in and out. Never send a float.\n\nEvery POST needs an Idempotency-Key: the same key with the same body replays the first answer, and the same key with a different body is refused. A retry on a bad network must never become a second sale.\n\nLimits: 120 calls a minute per key, 600 per address; answers stay replayable for 7 days.",
        "contact": {
            "name": "Developer support",
            "url": "https://tourismrevenue.co/developers",
            "email": "support@tourismrevenue.co"
        },
        "x-generated-from": "app/routes.php"
    },
    "servers": [
        {
            "url": "https://tourismrevenue.co",
            "description": "The platform. A sk_test_ key on this same host answers from the sandbox."
        }
    ],
    "security": [
        {
            "ApiKey": []
        }
    ],
    "tags": [
        {
            "name": "Diagnostics",
            "description": "Prove a key works before anything is built on it."
        },
        {
            "name": "Invoices",
            "description": "Issue, read and correct fiscal invoices. This is where the levy is charged."
        },
        {
            "name": "Documents",
            "description": "Fiscal documents received from suppliers, and the buyer's answer to them."
        },
        {
            "name": "Operators",
            "description": "The business this key acts for, whether it can issue, and asking a new one for consent."
        },
        {
            "name": "Reference",
            "description": "The tariff, the charge categories, the code lists and the currency rule — read these, never hard-code them."
        },
        {
            "name": "Remittances",
            "description": "What the business owes, what it has paid, and how to pay it."
        },
        {
            "name": "Tickets",
            "description": "High-volume gate admissions and the day-sheets they close into."
        },
        {
            "name": "Webhooks",
            "description": "Endpoints we deliver events to, and the signed deliveries themselves."
        }
    ],
    "paths": {
        "/api/v1/ping": {
            "get": {
                "operationId": "ping",
                "summary": "Check a key works",
                "description": "Answers 200 for any key that is valid, unrevoked and unexpired. It needs no scope and no X-Operator-Code, so it is the first call to make on the day a key is issued — before any business has authorised you. The answer says which environment the key resolves to; if that says sandbox when you expected live, stop and fix it here rather than three endpoints later.",
                "tags": [
                    "Diagnostics"
                ],
                "parameters": [],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Ping"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": null,
                "x-idempotent": false
            }
        },
        "/api/v1/whoami": {
            "get": {
                "operationId": "whoami",
                "summary": "Describe the calling key",
                "description": "The key's owner, environment and scopes — and, when X-Operator-Code is present, the business it is acting for and the scopes that business has actually granted, which may be narrower. Read this before debugging a 403; quote it in a support ticket. The key itself is never echoed, only its public prefix.",
                "tags": [
                    "Diagnostics"
                ],
                "parameters": [],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/WhoAmI"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": null,
                "x-idempotent": false
            }
        },
        "/api/v1/invoices": {
            "post": {
                "operationId": "issueInvoice",
                "summary": "Issue an invoice",
                "description": "Prices the lines against the tariff in force at the tax point, builds the canonical fiscal document and puts it through the tax service inline, so a till gets the IRN and the QR back in the same round trip it made the sale in. Send \"async\": true to have the lodgement queued instead and poll the document — either way the DOCUMENT exists before this returns. This is the call that charges the levy, so it is idempotent by construction: the same Idempotency-Key with the same body returns the first answer and issues nothing further.",
                "tags": [
                    "Invoices"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "responses": {
                    "201": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Invoice"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/E400"
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "409": {
                        "$ref": "#/components/responses/E409"
                    },
                    "415": {
                        "$ref": "#/components/responses/E415"
                    },
                    "422": {
                        "$ref": "#/components/responses/E422"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "invoices:write",
                "x-idempotent": true,
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/InvoiceCreate"
                            },
                            "example": {
                                "kind": "B2C",
                                "document_type": "customer_invoice",
                                "external_ref": "folio-10482",
                                "customer": {
                                    "name": "Adaeze Okafor",
                                    "phone": "08030000000",
                                    "email": "guest@example.ng"
                                },
                                "lines": [
                                    {
                                        "category": "ROOM_NIGHT",
                                        "description": "Deluxe room · 2 nights",
                                        "quantity": 2,
                                        "unit_price": 4500000
                                    },
                                    {
                                        "category": "SERVICE_CHARGE",
                                        "description": "Service charge",
                                        "quantity": 1,
                                        "unit_price": 450000
                                    }
                                ],
                                "payment_status": "paid",
                                "payment_means_code": "42"
                            }
                        }
                    }
                }
            },
            "get": {
                "operationId": "listInvoices",
                "summary": "List invoices",
                "description": "The documents this business has issued, newest first. A sandbox key sees sandbox documents and a live key sees live ones: the two money worlds never appear in one list, and the count is deliberately per-page rather than a total, because a total across both worlds would tell a test key how many real documents exist.",
                "tags": [
                    "Invoices"
                ],
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "description": "One document status, e.g. confirmed.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "kind",
                        "in": "query",
                        "required": false,
                        "description": "B2C, B2B or B2G.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "type",
                        "in": "query",
                        "required": false,
                        "description": "A document type, e.g. customer_invoice.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "required": false,
                        "description": "Issue date on or after this date (YYYY-MM-DD).",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "required": false,
                        "description": "Issue date on or before this date (YYYY-MM-DD).",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "search",
                        "in": "query",
                        "required": false,
                        "description": "Free text over number, reference and customer.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "required": false,
                        "description": "Page number, from 1.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "required": false,
                        "description": "Rows per page (maximum 100).",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/InvoiceList"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "invoices:read",
                "x-idempotent": false
            }
        },
        "/api/v1/invoices/preview": {
            "post": {
                "operationId": "previewInvoice",
                "summary": "Price a sale without issuing it",
                "description": "Runs exactly the pricing the issue call would run — the same tariff version, the same exemptions, the same rounding — and returns the totals and the priced lines. No document, no IRN, no levy. Show the guest this total; issue the same body afterwards and the figures will match. It still takes an Idempotency-Key: one POST helper on your side, one rule to remember.",
                "tags": [
                    "Invoices"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Preview"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/E400"
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "409": {
                        "$ref": "#/components/responses/E409"
                    },
                    "415": {
                        "$ref": "#/components/responses/E415"
                    },
                    "422": {
                        "$ref": "#/components/responses/E422"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "invoices:write",
                "x-idempotent": true,
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/InvoiceCreate"
                            },
                            "example": {
                                "kind": "B2C",
                                "lines": [
                                    {
                                        "category": "ROOM_NIGHT",
                                        "description": "Standard room · 1 night",
                                        "quantity": 1,
                                        "unit_price": 3500000
                                    }
                                ]
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/invoices/bulk": {
            "post": {
                "operationId": "issueInvoicesBulk",
                "summary": "Issue a batch of invoices",
                "description": "For a till that has been offline: send the sales it took while it could not reach us, oldest first. Every row is priced and validated BEFORE any document is issued, the per-row outcome is durable (poll the batch long after this request has gone), and a batch whose content has been sent before is refused rather than issued twice. The documents are created in this request; the tax service half is queued, so watch the batch or subscribe to invoice.signed.",
                "tags": [
                    "Invoices"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "responses": {
                    "202": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Batch"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/E400"
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "409": {
                        "$ref": "#/components/responses/E409"
                    },
                    "415": {
                        "$ref": "#/components/responses/E415"
                    },
                    "422": {
                        "$ref": "#/components/responses/E422"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "invoices:write",
                "x-idempotent": true,
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/InvoiceBulk"
                            },
                            "example": {
                                "rows": [
                                    {
                                        "external_ref": "till-3-2026-09-04-0001",
                                        "issued_at": "2026-09-04 19:41:00",
                                        "kind": "B2C",
                                        "lines": [
                                            {
                                                "category": "FOOD_BEVERAGE",
                                                "description": "Dinner",
                                                "quantity": 1,
                                                "unit_price": 1250000
                                            }
                                        ]
                                    }
                                ]
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/invoices/{uid}": {
            "get": {
                "operationId": "getInvoice",
                "summary": "Retrieve one invoice",
                "description": "One document in full: its lines, its taxes, its parties, its levy and where it has got to with the tax service. Poll this after an async issue if you would rather not wait for the invoice.confirmed webhook.",
                "tags": [
                    "Invoices"
                ],
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The document uid returned when it was issued (26 characters).",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Invoice"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "invoices:read",
                "x-idempotent": false
            }
        },
        "/api/v1/invoices/{uid}/pdf": {
            "get": {
                "operationId": "getInvoicePdf",
                "summary": "Download the fiscal PDF",
                "description": "The customer's copy, with the QR code and the verification address on it. The only endpoint here that does not answer JSON — a PDF base64'd into an envelope is a third larger and has to be decoded before it can reach a printer. Every REFUSAL on this route is still the usual envelope, so your error handling is unchanged.",
                "tags": [
                    "Invoices"
                ],
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The document uid.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "The fiscal PDF.",
                        "content": {
                            "application/pdf": {
                                "schema": {
                                    "type": "string",
                                    "format": "binary"
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "invoices:read",
                "x-idempotent": false
            }
        },
        "/api/v1/invoices/{uid}/qr": {
            "get": {
                "operationId": "getInvoiceQr",
                "summary": "Get the fiscal QR",
                "description": "JSON by default: a data URI a till can drop straight into its receipt template, plus the verification URL the QR encodes. Add ?format=png for the image bytes if you would rather not decode base64.",
                "tags": [
                    "Invoices"
                ],
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The document uid.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "format",
                        "in": "query",
                        "required": false,
                        "description": "png for the image bytes; omit for JSON.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Qr"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "invoices:read",
                "x-idempotent": false
            }
        },
        "/api/v1/invoices/{uid}/einvoice": {
            "get": {
                "operationId": "getInvoiceEinvoice",
                "summary": "The signed e-invoice, as sent",
                "description": "The canonical document as it was signed, with the tax service's answer. This is the endpoint an accounting package archives. The document arrives as a STRING, not a nested object, and deliberately so: the signature covers THOSE bytes, and re-serialising them through our encoder would reorder keys and reformat decimals until the archive you kept was no longer the thing that was signed.",
                "tags": [
                    "Invoices"
                ],
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The document uid.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/EInvoiceArchive"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "invoices:read",
                "x-idempotent": false
            }
        },
        "/api/v1/invoices/{uid}/credit-note": {
            "post": {
                "operationId": "issueCreditNote",
                "summary": "Credit an invoice",
                "description": "The only way to reverse or reduce a document that has already been lodged. It is a fiscal document in its own right (type 381), it references the original, and the levy it reverses is credited back on the ledger. Omit the lines to credit the invoice in full.",
                "tags": [
                    "Invoices"
                ],
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The uid of the invoice being corrected.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "responses": {
                    "201": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Invoice"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/E400"
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "409": {
                        "$ref": "#/components/responses/E409"
                    },
                    "415": {
                        "$ref": "#/components/responses/E415"
                    },
                    "422": {
                        "$ref": "#/components/responses/E422"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "invoices:write",
                "x-idempotent": true,
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/Adjustment"
                            },
                            "example": {
                                "reason": "Room rate corrected after the guest complained at checkout.",
                                "lines": [
                                    {
                                        "category": "ROOM_NIGHT",
                                        "description": "Rate correction",
                                        "quantity": 1,
                                        "unit_price": 500000
                                    }
                                ]
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/invoices/{uid}/debit-note": {
            "post": {
                "operationId": "issueDebitNote",
                "summary": "Charge more against an invoice",
                "description": "A further charge on a document that has already been lodged (type 383) — a minibar bill found after checkout, a late cancellation fee. It carries its own levy and it references the original.",
                "tags": [
                    "Invoices"
                ],
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The uid of the original invoice.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "responses": {
                    "201": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Invoice"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/E400"
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "409": {
                        "$ref": "#/components/responses/E409"
                    },
                    "415": {
                        "$ref": "#/components/responses/E415"
                    },
                    "422": {
                        "$ref": "#/components/responses/E422"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "invoices:write",
                "x-idempotent": true,
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/Adjustment"
                            },
                            "example": {
                                "reason": "Minibar consumption found after departure.",
                                "lines": [
                                    {
                                        "category": "FOOD_BEVERAGE",
                                        "description": "Minibar",
                                        "quantity": 1,
                                        "unit_price": 320000
                                    }
                                ]
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/invoices/{uid}/correction": {
            "post": {
                "operationId": "issueCorrection",
                "summary": "Reissue a corrected invoice",
                "description": "Replaces a document's content with corrected content (type 384), referencing what it corrects. Use it when the figures were right but the document was wrong — a mistyped TIN, the wrong buyer. Where the money changes, credit and reissue instead.",
                "tags": [
                    "Invoices"
                ],
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The uid of the document being corrected.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "responses": {
                    "201": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Invoice"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/E400"
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "409": {
                        "$ref": "#/components/responses/E409"
                    },
                    "415": {
                        "$ref": "#/components/responses/E415"
                    },
                    "422": {
                        "$ref": "#/components/responses/E422"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "invoices:write",
                "x-idempotent": true,
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/Adjustment"
                            },
                            "example": {
                                "reason": "Buyer TIN was mistyped at the desk."
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/batches/{id}": {
            "get": {
                "operationId": "getBatch",
                "summary": "How a bulk request turned out",
                "description": "The outcome of a bulk submission, row by row: what was issued, what was refused and why. It stays answerable long after the request that created it, which is what makes an offline catch-up auditable rather than hopeful.",
                "tags": [
                    "Invoices"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The batch id returned by the bulk call.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Batch"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "invoices:read",
                "x-idempotent": false
            }
        },
        "/api/v1/documents/received": {
            "get": {
                "operationId": "listReceivedDocuments",
                "summary": "The inbox",
                "description": "Fiscal documents OTHER businesses have issued to this one — what a bookkeeping integration reconciles payables against. ?response=pending returns exactly the ones still owed an answer, which is the query worth running on a timer, and each row carries the seconds left on its 72-hour deadline so you can escalate without doing date arithmetic against our clock.",
                "tags": [
                    "Documents"
                ],
                "parameters": [
                    {
                        "name": "response",
                        "in": "query",
                        "required": false,
                        "description": "pending, accepted or rejected.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "from",
                        "in": "query",
                        "required": false,
                        "description": "Received on or after (YYYY-MM-DD).",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "to",
                        "in": "query",
                        "required": false,
                        "description": "Received on or before (YYYY-MM-DD).",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "required": false,
                        "description": "Page number, from 1.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "per_page",
                        "in": "query",
                        "required": false,
                        "description": "Rows per page (maximum 100).",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/DocumentList"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "documents:read",
                "x-idempotent": false
            }
        },
        "/api/v1/documents/{uid}/accept": {
            "post": {
                "operationId": "acceptDocument",
                "summary": "Accept a document",
                "description": "The buyer agrees the document is correct. The answer goes on to the tax service and stops the deadline clock.",
                "tags": [
                    "Documents"
                ],
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The received document's uid.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/BuyerResponse"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/E400"
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "409": {
                        "$ref": "#/components/responses/E409"
                    },
                    "415": {
                        "$ref": "#/components/responses/E415"
                    },
                    "422": {
                        "$ref": "#/components/responses/E422"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "documents:write",
                "x-idempotent": true,
                "x-unreachable": "The door computes the scope \"documents:write\" for this endpoint, which is not a scope any key can hold: it is refused insufficient_scope until its resource is mapped in ApiKeyAuth::RESOURCE_SCOPES.",
                "deprecated": true,
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BuyerAccept"
                            },
                            "example": {
                                "note": "Matched to purchase order PO-8841."
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/documents/{uid}/reject": {
            "post": {
                "operationId": "rejectDocument",
                "summary": "Reject a document",
                "description": "The buyer disputes it. A reason is required and is sent on: rejection obliges the supplier to credit and reissue, and \"rejected\" with no explanation turns a two-day correction into a fortnight of telephone calls.",
                "tags": [
                    "Documents"
                ],
                "parameters": [
                    {
                        "name": "uid",
                        "in": "path",
                        "required": true,
                        "description": "The received document's uid.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/BuyerResponse"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/E400"
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "409": {
                        "$ref": "#/components/responses/E409"
                    },
                    "415": {
                        "$ref": "#/components/responses/E415"
                    },
                    "422": {
                        "$ref": "#/components/responses/E422"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "documents:write",
                "x-idempotent": true,
                "x-unreachable": "The door computes the scope \"documents:write\" for this endpoint, which is not a scope any key can hold: it is refused insufficient_scope until its resource is mapped in ApiKeyAuth::RESOURCE_SCOPES.",
                "deprecated": true,
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/BuyerReject"
                            },
                            "example": {
                                "reason": "Quantity billed does not match the delivery note."
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/operators/me": {
            "get": {
                "operationId": "getOperator",
                "summary": "The business this key acts for",
                "description": "The register's record of the operator named in X-Operator-Code (or the one an operator-owned key is bound to): its code, its legal name, its trade, its premises. Codes and names, never our primary keys — an id you stored would be a number that means nothing outside our database and that we have never promised to keep.",
                "tags": [
                    "Operators"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Operator"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "operators:read",
                "x-idempotent": false
            }
        },
        "/api/v1/operators/me/einvoicing": {
            "get": {
                "operationId": "getEinvoicingReadiness",
                "summary": "Can this business issue right now?",
                "description": "\"ready\" is the whole answer a till needs before it offers to issue: true only when a credential actually resolves for this business in THIS environment. When it is false the reason is given as text, because the fix is always somebody's action — enter your tax-service keys, finish onboarding — and a machine code would not tell them which. Call it at start-up.",
                "tags": [
                    "Operators"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/EInvoicingReadiness"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "operators:read",
                "x-idempotent": false
            }
        },
        "/api/v1/operators/link": {
            "post": {
                "operationId": "requestOperatorLink",
                "summary": "Ask a business for consent",
                "description": "Raises a link request against a business by its operator code. It grants nothing: the business accepts it in its own portal, and until it does, every call naming that business is refused operator_not_linked. THE INVITE CODE IS NOT RETURNED — an answer to a POST is stored for idempotent replay, and a code stored anywhere is a code somebody else could redeem. \"No such business\" and \"that business is not open to linking\" answer identically, so a vendor cannot walk the operator register from a refusal message.",
                "tags": [
                    "Operators"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "responses": {
                    "202": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/LinkRequestResult"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/E400"
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "409": {
                        "$ref": "#/components/responses/E409"
                    },
                    "415": {
                        "$ref": "#/components/responses/E415"
                    },
                    "422": {
                        "$ref": "#/components/responses/E422"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "operators:write",
                "x-idempotent": true,
                "x-unreachable": "The door computes the scope \"operators:write\" for this endpoint, which is not a scope any key can hold: it is refused insufficient_scope until its resource is mapped in ApiKeyAuth::RESOURCE_SCOPES.",
                "deprecated": true,
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/LinkRequest"
                            },
                            "example": {
                                "operator_code": "LAG-HTL-0042",
                                "scopes": [
                                    "invoices:read",
                                    "invoices:write"
                                ],
                                "note": "Front-desk till integration"
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/tariff": {
            "get": {
                "operationId": "getTariff",
                "summary": "The levy schedule in force",
                "description": "The Tourism Development Contribution schedule that governs today, already narrowed to the pilot and the state of the business you are acting for. Cells are published by CODE, never by our primary keys, and \"*\" in a dimension means every value of it. Never hard-code a rate: it is set by an approved tariff version and it can change between one booking and the next.",
                "tags": [
                    "Reference"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Tariff"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "operators:read",
                "x-idempotent": false
            }
        },
        "/api/v1/charge-categories": {
            "get": {
                "operationId": "listChargeCategories",
                "summary": "What this business may bill for",
                "description": "The charge lines this business may put on an invoice, with the ones its trade uses first, and whether each attracts the levy. A till renders its buttons from this rather than from a list someone typed into its configuration two versions ago.",
                "tags": [
                    "Reference"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/ChargeCategories"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "operators:read",
                "x-idempotent": false
            }
        },
        "/api/v1/resources/{kind}": {
            "get": {
                "operationId": "getResources",
                "summary": "A tax-service code list",
                "description": "The code lists a document is VALIDATED against before it can be signed — currencies, invoice types, payment means, tax categories. Build your dropdowns from these and you cannot send us a code we will reject. They are served for the KEY'S environment: the sandbox catalogue and the live one are different lists, and a sandbox key must never be shown the live one and believe it has been checked.",
                "tags": [
                    "Reference"
                ],
                "parameters": [
                    {
                        "name": "kind",
                        "in": "path",
                        "required": true,
                        "description": "The list to fetch, e.g. currencies, invoice-types, payment-means, tax-categories.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/ResourceList"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "operators:read",
                "x-idempotent": false
            }
        },
        "/api/v1/fx": {
            "get": {
                "operationId": "getFx",
                "summary": "The currency rule",
                "description": "What currency the levy is computed in, and the rule for a document that is not in it. The platform does not invent an exchange rate: a document in another currency carries the rate the SELLER used, and it is rejected without one. Where no reference rate has been published, this says so plainly rather than handing your till a number we made up — a levy computed against an invented rate is a reconciliation ticket with a date on it.",
                "tags": [
                    "Reference"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Fx"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "operators:read",
                "x-idempotent": false
            }
        },
        "/api/v1/remittances": {
            "get": {
                "operationId": "listRemittances",
                "summary": "The periods and the position",
                "description": "What this business owes, what it has paid and when the next payment falls due — the figures behind the \"TDC due\" line an accounting integration shows its user, reconciled to the levy ledger.",
                "tags": [
                    "Remittances"
                ],
                "parameters": [
                    {
                        "name": "status",
                        "in": "query",
                        "required": false,
                        "description": "open, issued, part_paid, paid, overdue.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "name": "year",
                        "in": "query",
                        "required": false,
                        "description": "Calendar year, e.g. 2026.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "page",
                        "in": "query",
                        "required": false,
                        "description": "Page number, from 1.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "name": "length",
                        "in": "query",
                        "required": false,
                        "description": "Rows per page.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/RemittanceList"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "levy:read",
                "x-idempotent": false
            }
        },
        "/api/v1/remittances/mandate": {
            "post": {
                "operationId": "createMandate",
                "summary": "Enrol a direct debit",
                "description": "Standing permission to collect the levy from the business's own account. AN INTEGRATOR KEY IS REFUSED HERE whatever it is linked for: the consent a business gives a vendor is permission to handle its fiscal documents, and taking money out of its bank account is not a side effect of that. A business that wants its vendor to set this up mints an operator-owned key, which is a decision it takes deliberately and can revoke on its own screen. Consent must be evidenced, and only the masked account is ever stored.",
                "tags": [
                    "Remittances"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "responses": {
                    "201": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Mandate"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/E400"
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "409": {
                        "$ref": "#/components/responses/E409"
                    },
                    "415": {
                        "$ref": "#/components/responses/E415"
                    },
                    "422": {
                        "$ref": "#/components/responses/E422"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "levy:write",
                "x-idempotent": true,
                "x-unreachable": "The door computes the scope \"levy:write\" for this endpoint, which is not a scope any key can hold: it is refused insufficient_scope until its resource is mapped in ApiKeyAuth::RESOURCE_SCOPES.",
                "deprecated": true,
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/MandateCreate"
                            },
                            "example": {
                                "bank_code": "070",
                                "account_number": "0123456789",
                                "account_name": "Lagoon Hotels Limited",
                                "consent_evidence": "Signed direct-debit instruction, 4 September 2026"
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/remittances/{ref}": {
            "get": {
                "operationId": "getRemittance",
                "summary": "One period in full",
                "description": "What the period bills, what has landed against it, and the account it is being collected on — with the evidence that reconciles the two.",
                "tags": [
                    "Remittances"
                ],
                "parameters": [
                    {
                        "name": "ref",
                        "in": "path",
                        "required": true,
                        "description": "The remittance reference, as it appears on the statement.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Remittance"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "levy:read",
                "x-idempotent": false
            }
        },
        "/api/v1/remittances/{ref}/pay": {
            "post": {
                "operationId": "payRemittance",
                "summary": "Get the payment instruction",
                "description": "Hands back how to pay a period: the account, the reference and the amount. A second call with the same Idempotency-Key replays the first answer, and a call with a NEW key still does not open a second account — the business may already have typed that account number into its banking app, and changing it underneath them is how a payment goes to a dead reference.",
                "tags": [
                    "Remittances"
                ],
                "parameters": [
                    {
                        "name": "ref",
                        "in": "path",
                        "required": true,
                        "description": "The remittance reference.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/PaymentInstruction"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/E400"
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "409": {
                        "$ref": "#/components/responses/E409"
                    },
                    "415": {
                        "$ref": "#/components/responses/E415"
                    },
                    "422": {
                        "$ref": "#/components/responses/E422"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "levy:write",
                "x-idempotent": true,
                "x-unreachable": "The door computes the scope \"levy:write\" for this endpoint, which is not a scope any key can hold: it is refused insufficient_scope until its resource is mapped in ApiKeyAuth::RESOURCE_SCOPES.",
                "deprecated": true,
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/PayRequest"
                            },
                            "example": {
                                "channel": "transfer"
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/tickets/bulk": {
            "post": {
                "operationId": "postTicketBatch",
                "summary": "Post a batch of gate taps",
                "description": "For attractions: admissions in bulk, up to a whole session at a time. The WHOLE batch is validated before any of it is recorded — a row with a malformed price must not leave half a morning's admissions in the ledger and half rejected, because nobody can tell from the day-sheet which half is missing. Once recording starts, a row the domain refuses is reported against its group and the rest still land.",
                "tags": [
                    "Tickets"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "responses": {
                    "202": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/TicketBulkResult"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/E400"
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "409": {
                        "$ref": "#/components/responses/E409"
                    },
                    "415": {
                        "$ref": "#/components/responses/E415"
                    },
                    "422": {
                        "$ref": "#/components/responses/E422"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "invoices:write",
                "x-idempotent": true,
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/TicketBulk"
                            },
                            "example": {
                                "rows": [
                                    {
                                        "premises_id": 12,
                                        "ticket_type": "Adult",
                                        "qty": 2,
                                        "unit_price": 150000,
                                        "device_code": "GATE1"
                                    },
                                    {
                                        "premises_id": 12,
                                        "ticket_type": "Child",
                                        "qty": 1,
                                        "unit_price": 75000,
                                        "device_code": "GATE1"
                                    }
                                ]
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/tickets/daysheets": {
            "get": {
                "operationId": "listDaysheets",
                "summary": "Day-sheets and running totals",
                "description": "The recent premises-days and where each one stands: still open, or closed with the day-sheet document it produced. ?premises_id adds the live running total for that gate, which is the screen a gate app renders behind its +1 buttons.",
                "tags": [
                    "Tickets"
                ],
                "parameters": [
                    {
                        "name": "premises_id",
                        "in": "query",
                        "required": false,
                        "description": "One gate, with its live running total.",
                        "schema": {
                            "type": "integer"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Daysheets"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "invoices:read",
                "x-idempotent": false
            }
        },
        "/api/v1/webhooks": {
            "get": {
                "operationId": "listWebhooks",
                "summary": "Endpoints, events and the signature scheme",
                "description": "This key's registered endpoints, plus everything needed to build a receiver without opening the documentation: the event catalogue, the signature scheme, the retry ladder and the limits. The scheme is published beside the endpoints because a receiver that verifies signatures wrongly fails in the one way nobody notices until an event matters. Signing secrets are never in this list.",
                "tags": [
                    "Webhooks"
                ],
                "parameters": [
                    {
                        "name": "mode",
                        "in": "query",
                        "required": false,
                        "description": "live or test.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/WebhookIndex"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "webhooks:manage",
                "x-idempotent": false
            },
            "post": {
                "operationId": "createWebhook",
                "summary": "Register a receiver",
                "description": "Registers an HTTPS URL and mints its signing secret. THE SECRET IS RETURNED ONCE, in this response, and can never be read again — store it before you close the connection. The URL is vetted before anything is stored and again before every delivery: https only, a public address, no userinfo, no private or link-local host. A webhook is an outbound request WE make on your say-so, so an unvetted URL would be a request forgery with our network behind it.",
                "tags": [
                    "Webhooks"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "responses": {
                    "201": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/WebhookWithSecret"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/E400"
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "409": {
                        "$ref": "#/components/responses/E409"
                    },
                    "415": {
                        "$ref": "#/components/responses/E415"
                    },
                    "422": {
                        "$ref": "#/components/responses/E422"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "webhooks:manage",
                "x-idempotent": true,
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WebhookCreate"
                            },
                            "example": {
                                "url": "https://api.yourcompany.com/hooks/tourismrevenue",
                                "events": [
                                    "invoice.confirmed",
                                    "invoice.failed",
                                    "remittance.due"
                                ],
                                "mode": "test",
                                "description": "Production till fleet"
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/webhooks/test": {
            "post": {
                "operationId": "testWebhook",
                "summary": "Send a signed test event",
                "description": "Delivers a signed webhook.ping to one of your endpoints so you can prove your signature check before a real invoice depends on it. It is a normal delivery — same signing, same retry ladder, same log — because a test that took a different path would prove nothing about the path that matters. The ping is not subscribable and is never fanned out to anybody else.",
                "tags": [
                    "Webhooks"
                ],
                "parameters": [
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    },
                    {
                        "$ref": "#/components/parameters/IdempotencyKey"
                    }
                ],
                "responses": {
                    "202": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Delivery"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "400": {
                        "$ref": "#/components/responses/E400"
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "409": {
                        "$ref": "#/components/responses/E409"
                    },
                    "415": {
                        "$ref": "#/components/responses/E415"
                    },
                    "422": {
                        "$ref": "#/components/responses/E422"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "webhooks:manage",
                "x-idempotent": true,
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/WebhookTest"
                            },
                            "example": {
                                "endpoint_id": 1
                            }
                        }
                    }
                }
            }
        },
        "/api/v1/webhooks/{id}": {
            "delete": {
                "operationId": "deleteWebhook",
                "summary": "Stop sending to a receiver",
                "description": "The endpoint goes; its deliveries do not. What we sent is evidence and is append-only, including for an endpoint somebody has since removed. Deleting twice is not an error, so this needs no Idempotency-Key.",
                "tags": [
                    "Webhooks"
                ],
                "parameters": [
                    {
                        "name": "id",
                        "in": "path",
                        "required": true,
                        "description": "The endpoint id.",
                        "schema": {
                            "type": "string"
                        }
                    },
                    {
                        "$ref": "#/components/parameters/OperatorCode"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "Success.",
                        "headers": {
                            "X-Request-Id": {
                                "description": "The handle to quote in a support ticket.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-Api-Environment": {
                                "description": "sandbox or live — which money world answered.",
                                "schema": {
                                    "type": "string"
                                }
                            },
                            "X-RateLimit-Remaining": {
                                "description": "Calls left in this minute for this key.",
                                "schema": {
                                    "type": "integer"
                                }
                            },
                            "Idempotent-Replay": {
                                "description": "Present and true when this is a stored answer rather than new work.",
                                "schema": {
                                    "type": "string"
                                }
                            }
                        },
                        "content": {
                            "application/json": {
                                "schema": {
                                    "allOf": [
                                        {
                                            "$ref": "#/components/schemas/Envelope"
                                        },
                                        {
                                            "type": "object",
                                            "properties": {
                                                "data": {
                                                    "$ref": "#/components/schemas/Deleted"
                                                }
                                            }
                                        }
                                    ]
                                }
                            }
                        }
                    },
                    "401": {
                        "$ref": "#/components/responses/E401"
                    },
                    "403": {
                        "$ref": "#/components/responses/E403"
                    },
                    "404": {
                        "$ref": "#/components/responses/E404"
                    },
                    "429": {
                        "$ref": "#/components/responses/E429"
                    },
                    "500": {
                        "$ref": "#/components/responses/E500"
                    }
                },
                "x-required-scope": "webhooks:manage",
                "x-idempotent": false
            }
        }
    },
    "components": {
        "securitySchemes": {
            "ApiKey": {
                "type": "http",
                "scheme": "bearer",
                "bearerFormat": "sk_live_… or sk_test_…",
                "description": "Your secret key, as \"Authorization: Bearer sk_live_…\". The mode is in the key: a sk_test_ key resolves to the sandbox and can never touch money. Keys are shown once, at creation; the platform stores only a hash and cannot recover one for you."
            }
        },
        "parameters": {
            "OperatorCode": {
                "name": "X-Operator-Code",
                "in": "header",
                "required": false,
                "description": "The business you are acting for. REQUIRED on an integrator key, which must also hold an active grant from that business (otherwise 403 operator_not_linked). An operator-owned key is bound to its own business: send its code or nothing, never another's.",
                "schema": {
                    "type": "string"
                },
                "example": "{{operator_code}}"
            },
            "IdempotencyKey": {
                "name": "Idempotency-Key",
                "in": "header",
                "required": true,
                "description": "A unique key for this attempt, 8–190 printable characters with no spaces (a UUID is ideal). The SAME key with the SAME body replays the first answer; the same key with a different body is refused 422 and never obeyed. Answers stay replayable for 7 days.",
                "schema": {
                    "type": "string",
                    "minLength": 8,
                    "maxLength": 190
                }
            }
        },
        "schemas": {
            "Envelope": {
                "type": "object",
                "required": [
                    "ok",
                    "data",
                    "request_id"
                ],
                "properties": {
                    "ok": {
                        "type": "boolean",
                        "const": true
                    },
                    "data": {
                        "type": "object"
                    },
                    "request_id": {
                        "type": "string",
                        "description": "This call's handle. Log it; quote it in tickets."
                    }
                }
            },
            "Error": {
                "type": "object",
                "required": [
                    "ok",
                    "error",
                    "request_id"
                ],
                "properties": {
                    "ok": {
                        "type": "boolean",
                        "const": false
                    },
                    "error": {
                        "type": "object",
                        "required": [
                            "code",
                            "message"
                        ],
                        "properties": {
                            "code": {
                                "type": "string",
                                "enum": [
                                    "unauthorized",
                                    "key_revoked",
                                    "key_expired",
                                    "forbidden",
                                    "insufficient_scope",
                                    "operator_not_linked",
                                    "operator_mismatch",
                                    "ip_not_allowed",
                                    "integrator_suspended",
                                    "live_not_enabled",
                                    "sandbox_only",
                                    "idempotency_key_required",
                                    "invalid_idempotency_key",
                                    "malformed_json",
                                    "not_found",
                                    "method_not_allowed",
                                    "conflict",
                                    "request_in_flight",
                                    "operator_not_ready",
                                    "payload_too_large",
                                    "unsupported_media_type",
                                    "invalid_request",
                                    "idempotency_mismatch",
                                    "unprocessable",
                                    "rate_limited",
                                    "server_error",
                                    "gateway_error",
                                    "service_unavailable"
                                ],
                                "description": "Branch on this, never on the message."
                            },
                            "message": {
                                "type": "string",
                                "description": "What happened and what to do next, in English."
                            },
                            "fields": {
                                "type": "object",
                                "additionalProperties": {
                                    "type": "string"
                                },
                                "description": "Present only when individual fields were refused."
                            }
                        }
                    },
                    "request_id": {
                        "type": "string"
                    }
                }
            },
            "Ping": {
                "type": "object",
                "properties": {
                    "pong": {
                        "type": "boolean"
                    },
                    "environment": {
                        "type": "string",
                        "enum": [
                            "sandbox",
                            "live"
                        ]
                    },
                    "time": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            },
            "WhoAmI": {
                "type": "object",
                "properties": {
                    "key_prefix": {
                        "type": "string",
                        "description": "The public prefix, e.g. sk_test_a1b2c3d4. Never the key."
                    },
                    "owner_type": {
                        "type": "string",
                        "enum": [
                            "integrator",
                            "operator"
                        ]
                    },
                    "environment": {
                        "type": "string",
                        "enum": [
                            "sandbox",
                            "live"
                        ]
                    },
                    "scopes": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "enum": [
                                "invoices:read",
                                "invoices:write",
                                "credit_notes:read",
                                "credit_notes:write",
                                "customers:read",
                                "customers:write",
                                "documents:read",
                                "operators:read",
                                "levy:read",
                                "webhooks:manage"
                            ]
                        },
                        "description": "What this key holds, already narrowed by the business's own grant."
                    },
                    "operator": {
                        "anyOf": [
                            {
                                "$ref": "#/components/schemas/Operator"
                            },
                            {
                                "type": "null"
                            }
                        ]
                    },
                    "rate_limit_per_min": {
                        "type": "integer"
                    }
                }
            },
            "Line": {
                "type": "object",
                "required": [
                    "description",
                    "quantity",
                    "unit_price"
                ],
                "properties": {
                    "category": {
                        "type": "string",
                        "description": "The charge category code, e.g. ROOM_NIGHT. GET /charge-categories lists the ones this business may use."
                    },
                    "description": {
                        "type": "string",
                        "maxLength": 255
                    },
                    "quantity": {
                        "type": "number",
                        "minimum": 0
                    },
                    "unit_price": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Price of one unit, before discount. In kobo."
                    },
                    "discount": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Discount on the line. In kobo."
                    },
                    "fee": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Charge added to the line. In kobo."
                    },
                    "domestic_amount": {
                        "type": "integer",
                        "format": "int64",
                        "description": "For a marketplace line: the part that is the host's. In kobo."
                    },
                    "commission_amount": {
                        "type": "integer",
                        "format": "int64",
                        "description": "For a marketplace line: your commission. In kobo."
                    },
                    "tdc_eligible": {
                        "type": "boolean",
                        "description": "Override only where the tariff allows it; the platform decides by category otherwise."
                    },
                    "pass_through": {
                        "type": "boolean",
                        "description": "A sum collected on somebody else's behalf; it does not attract the levy."
                    },
                    "sellers_item_id": {
                        "type": "string"
                    },
                    "period_start": {
                        "type": "string",
                        "format": "date"
                    },
                    "period_end": {
                        "type": "string",
                        "format": "date"
                    },
                    "room_ref": {
                        "type": "string"
                    }
                }
            },
            "CustomerInput": {
                "type": "object",
                "description": "Omit it entirely for a walk-in guest; a B2B or B2G sale needs a name and a TIN.",
                "properties": {
                    "name": {
                        "type": "string"
                    },
                    "tin": {
                        "type": "string",
                        "description": "Required for a B2B or B2G sale."
                    },
                    "email": {
                        "type": "string",
                        "format": "email"
                    },
                    "phone": {
                        "type": "string"
                    },
                    "address": {
                        "type": "string"
                    },
                    "city": {
                        "type": "string"
                    },
                    "lga": {
                        "type": "string"
                    },
                    "state": {
                        "type": "string"
                    },
                    "country": {
                        "type": "string",
                        "default": "NG"
                    },
                    "postal_zone": {
                        "type": "string"
                    },
                    "description": {
                        "type": "string"
                    }
                }
            },
            "InvoiceCreate": {
                "type": "object",
                "required": [
                    "lines"
                ],
                "description": "Only the fields listed here cross the boundary; anything else is ignored rather than forwarded, so a new key in your request can never reach the domain by accident.",
                "properties": {
                    "kind": {
                        "type": "string",
                        "enum": [
                            "B2C",
                            "B2B",
                            "B2G"
                        ],
                        "default": "B2C"
                    },
                    "document_type": {
                        "type": "string",
                        "enum": [
                            "customer_invoice",
                            "customer_receipt",
                            "prepayment_invoice",
                            "self_billed_invoice"
                        ],
                        "default": "customer_invoice"
                    },
                    "lines": {
                        "type": "array",
                        "minItems": 1,
                        "items": {
                            "$ref": "#/components/schemas/Line"
                        }
                    },
                    "customer": {
                        "$ref": "#/components/schemas/CustomerInput"
                    },
                    "premises_id": {
                        "type": "integer",
                        "description": "Which of the business's premises made the sale."
                    },
                    "invoice_number": {
                        "type": "string",
                        "maxLength": 80,
                        "description": "Your own number. Unique per business per environment; a repeat is refused 409."
                    },
                    "external_ref": {
                        "type": "string",
                        "maxLength": 80,
                        "description": "Your order or folio reference. It is the SECOND exactly-once guard behind the Idempotency-Key: a repeat is refused 409 with the uid of the document that already exists."
                    },
                    "note": {
                        "type": "string",
                        "maxLength": 500
                    },
                    "payment_status": {
                        "type": "string",
                        "enum": [
                            "unpaid",
                            "part_paid",
                            "paid",
                            "refunded"
                        ],
                        "default": "paid"
                    },
                    "payment_means_code": {
                        "type": "string",
                        "maxLength": 10,
                        "description": "UN/ECE 4461 code, e.g. 42 for a bank transfer."
                    },
                    "due_date": {
                        "type": "string",
                        "format": "date"
                    },
                    "tax_point_date": {
                        "type": "string",
                        "format": "date"
                    },
                    "prepaid": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Already paid against this invoice. In kobo."
                    },
                    "order_reference": {
                        "type": "string",
                        "maxLength": 80
                    },
                    "buyer_reference": {
                        "type": "string",
                        "maxLength": 80
                    },
                    "delivery_period": {
                        "type": "object",
                        "properties": {
                            "start": {
                                "type": "string",
                                "format": "date"
                            },
                            "end": {
                                "type": "string",
                                "format": "date"
                            }
                        }
                    },
                    "issued_at": {
                        "type": "string",
                        "description": "When YOUR till issued it (YYYY-MM-DD HH:MM:SS). Send it for a sale taken offline: the statutory clock runs from the sale, not from the moment the network recovered."
                    },
                    "async": {
                        "type": "boolean",
                        "default": false,
                        "description": "Queue the tax-service half instead of waiting for it. The document exists either way."
                    }
                }
            },
            "InvoiceBulk": {
                "type": "object",
                "required": [
                    "rows"
                ],
                "properties": {
                    "rows": {
                        "type": "array",
                        "minItems": 1,
                        "description": "Sales in the order they were taken. Give each an external_ref: it is what makes a resent batch issue each sale once.",
                        "items": {
                            "$ref": "#/components/schemas/InvoiceCreate"
                        }
                    }
                }
            },
            "Amounts": {
                "type": "object",
                "description": "Every figure in kobo.",
                "properties": {
                    "line_extension": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Lines before tax. In kobo."
                    },
                    "allowances": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Discounts. In kobo."
                    },
                    "charges": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Additional charges. In kobo."
                    },
                    "tax_exclusive": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Net of tax. In kobo."
                    },
                    "tax_inclusive": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Gross. In kobo."
                    },
                    "tdc_base": {
                        "type": "integer",
                        "format": "int64",
                        "description": "The part of the sale the levy is charged on. In kobo."
                    },
                    "tdc": {
                        "type": "integer",
                        "format": "int64",
                        "description": "The Tourism Development Contribution. In kobo."
                    },
                    "vat": {
                        "type": "integer",
                        "format": "int64",
                        "description": "VAT. In kobo."
                    },
                    "state_tax": {
                        "type": "integer",
                        "format": "int64",
                        "description": "State consumption tax, where one applies. In kobo."
                    },
                    "prepaid": {
                        "type": "integer",
                        "format": "int64",
                        "description": "Already paid. In kobo."
                    },
                    "payable": {
                        "type": "integer",
                        "format": "int64",
                        "description": "What the guest pays. In kobo."
                    }
                }
            },
            "Invoice": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "string",
                        "description": "Same as uid — 26 characters, the document's identity everywhere in this API."
                    },
                    "object": {
                        "type": "string",
                        "const": "invoice"
                    },
                    "uid": {
                        "type": "string"
                    },
                    "invoice_number": {
                        "type": "string"
                    },
                    "irn": {
                        "type": "string",
                        "description": "The tax service's reference. Empty until the document is signed."
                    },
                    "document_type": {
                        "type": "string",
                        "enum": [
                            "customer_invoice",
                            "customer_receipt",
                            "ticket_daysheet",
                            "credit_note",
                            "debit_note",
                            "corrected_invoice",
                            "prepayment_invoice",
                            "self_billed_invoice",
                            "factored_invoice",
                            "remittance_invoice",
                            "platform_fee_invoice",
                            "integrator_fee_invoice",
                            "bank_fee_invoice",
                            "platform_share_invoice",
                            "penalty_notice",
                            "demand_notice",
                            "vendor_invoice"
                        ]
                    },
                    "kind": {
                        "type": "string",
                        "enum": [
                            "B2B",
                            "B2G",
                            "B2C"
                        ]
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "draft",
                            "finalised",
                            "validated",
                            "signed",
                            "transmitted",
                            "confirmed",
                            "accepted",
                            "rejected_by_buyer",
                            "cancelled",
                            "exempt",
                            "validation_failed",
                            "sign_failed",
                            "transmit_failed",
                            "expired_unlodged"
                        ]
                    },
                    "model": {
                        "type": "string",
                        "enum": [
                            "clearance",
                            "reporting",
                            "exempt"
                        ]
                    },
                    "environment": {
                        "type": "string",
                        "enum": [
                            "sandbox",
                            "live"
                        ]
                    },
                    "issue_date": {
                        "type": "string",
                        "format": "date"
                    },
                    "issue_time": {
                        "type": "string"
                    },
                    "issued_at": {
                        "type": "string",
                        "description": "When the seller's own system issued it."
                    },
                    "payment_status": {
                        "type": "string",
                        "enum": [
                            "unpaid",
                            "part_paid",
                            "paid",
                            "refunded"
                        ]
                    },
                    "external_ref": {
                        "type": "string"
                    },
                    "amounts": {
                        "$ref": "#/components/schemas/Amounts"
                    },
                    "tdc_rate_bp": {
                        "type": "integer",
                        "description": "The levy rate this document was priced at, in basis points. 100 = 1%."
                    },
                    "lines": {
                        "type": "array",
                        "items": {
                            "type": "object"
                        }
                    },
                    "parties": {
                        "type": "object",
                        "description": "Supplier and customer as they stood at the tax point."
                    },
                    "pipeline": {
                        "type": "object",
                        "description": "What the tax-service pipeline actually did, step by step — a dropped connection and a refusal leave the same status behind, and only one is worth a retry."
                    },
                    "verify_url": {
                        "type": "string",
                        "description": "Where anyone can check this document without an account."
                    },
                    "links": {
                        "type": "object",
                        "properties": {
                            "self": {
                                "type": "string"
                            },
                            "pdf": {
                                "type": "string"
                            },
                            "qr": {
                                "type": "string"
                            },
                            "einvoice": {
                                "type": "string"
                            }
                        }
                    }
                }
            },
            "InvoiceSummary": {
                "type": "object",
                "description": "The list row: enough to render a table, not the whole document.",
                "properties": {
                    "id": {
                        "type": "string"
                    },
                    "object": {
                        "type": "string",
                        "const": "invoice"
                    },
                    "uid": {
                        "type": "string"
                    },
                    "invoice_number": {
                        "type": "string"
                    },
                    "irn": {
                        "type": "string"
                    },
                    "document_type": {
                        "type": "string"
                    },
                    "kind": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string"
                    },
                    "environment": {
                        "type": "string"
                    },
                    "issue_date": {
                        "type": "string",
                        "format": "date"
                    },
                    "customer_name": {
                        "type": "string"
                    },
                    "external_ref": {
                        "type": "string"
                    },
                    "amounts": {
                        "type": "object",
                        "properties": {
                            "payable": {
                                "type": "integer",
                                "format": "int64",
                                "description": "What the guest paid. In kobo."
                            },
                            "tdc": {
                                "type": "integer",
                                "format": "int64",
                                "description": "The levy. In kobo."
                            },
                            "vat": {
                                "type": "integer",
                                "format": "int64",
                                "description": "VAT. In kobo."
                            },
                            "state_tax": {
                                "type": "integer",
                                "format": "int64",
                                "description": "State consumption tax. In kobo."
                            }
                        }
                    },
                    "links": {
                        "type": "object",
                        "properties": {
                            "self": {
                                "type": "string"
                            }
                        }
                    }
                }
            },
            "InvoiceList": {
                "type": "object",
                "properties": {
                    "object": {
                        "type": "string",
                        "const": "list"
                    },
                    "data": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/InvoiceSummary"
                        }
                    },
                    "page": {
                        "type": "integer"
                    },
                    "per_page": {
                        "type": "integer"
                    },
                    "count": {
                        "type": "integer",
                        "description": "Rows on THIS page."
                    },
                    "has_more": {
                        "type": "boolean",
                        "description": "Page again while this is true."
                    }
                }
            },
            "DocumentList": {
                "type": "object",
                "properties": {
                    "object": {
                        "type": "string",
                        "const": "list"
                    },
                    "data": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/ReceivedDocument"
                        }
                    },
                    "page": {
                        "type": "integer"
                    },
                    "per_page": {
                        "type": "integer"
                    },
                    "count": {
                        "type": "integer",
                        "description": "Rows on THIS page."
                    },
                    "has_more": {
                        "type": "boolean",
                        "description": "Page again while this is true."
                    }
                }
            },
            "Preview": {
                "type": "object",
                "description": "What the sale would come to. Nothing was created and no levy accrued.",
                "properties": {
                    "object": {
                        "type": "string",
                        "const": "preview"
                    },
                    "lines": {
                        "type": "array",
                        "items": {
                            "type": "object"
                        }
                    },
                    "amounts": {
                        "$ref": "#/components/schemas/Amounts"
                    },
                    "tdc_rate_bp": {
                        "type": "integer"
                    }
                }
            },
            "Adjustment": {
                "type": "object",
                "required": [
                    "reason"
                ],
                "properties": {
                    "reason": {
                        "type": "string",
                        "maxLength": 255,
                        "description": "Why. It is kept with the document and shown on it."
                    },
                    "lines": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Line"
                        },
                        "description": "What to adjust. Omit to adjust the whole document."
                    }
                }
            },
            "Qr": {
                "type": "object",
                "properties": {
                    "data_uri": {
                        "type": "string",
                        "description": "A PNG data URI, ready to drop into a receipt template."
                    },
                    "verify_url": {
                        "type": "string",
                        "description": "What the QR encodes."
                    }
                }
            },
            "EInvoiceArchive": {
                "type": "object",
                "properties": {
                    "invoice": {
                        "type": "string",
                        "description": "The canonical document AS SIGNED, verbatim. A string, because the signature covers these bytes."
                    },
                    "canonical_hash": {
                        "type": "string"
                    },
                    "csid": {
                        "type": "string",
                        "description": "The tax service's signature."
                    },
                    "irn": {
                        "type": "string"
                    },
                    "response": {
                        "type": "object",
                        "description": "What the tax service answered."
                    }
                }
            },
            "Batch": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "object": {
                        "type": "string",
                        "const": "batch"
                    },
                    "status": {
                        "type": "string"
                    },
                    "rows": {
                        "type": "integer"
                    },
                    "issued": {
                        "type": "integer"
                    },
                    "rejected": {
                        "type": "integer"
                    },
                    "results": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "external_ref": {
                                    "type": "string"
                                },
                                "ok": {
                                    "type": "boolean"
                                },
                                "uid": {
                                    "type": "string"
                                },
                                "error": {
                                    "type": "object"
                                }
                            }
                        }
                    },
                    "links": {
                        "type": "object",
                        "properties": {
                            "self": {
                                "type": "string"
                            }
                        }
                    }
                }
            },
            "ReceivedDocument": {
                "type": "object",
                "properties": {
                    "uid": {
                        "type": "string"
                    },
                    "object": {
                        "type": "string",
                        "const": "document"
                    },
                    "irn": {
                        "type": "string"
                    },
                    "supplier_name": {
                        "type": "string"
                    },
                    "supplier_tin": {
                        "type": "string"
                    },
                    "issue_date": {
                        "type": "string",
                        "format": "date"
                    },
                    "amounts": {
                        "type": "object"
                    },
                    "buyer_response": {
                        "type": "string",
                        "enum": [
                            "pending",
                            "accepted",
                            "rejected"
                        ]
                    },
                    "respond_by": {
                        "type": "string",
                        "format": "date-time"
                    },
                    "seconds_remaining": {
                        "type": "integer",
                        "description": "On the 72-hour answer deadline. Escalate on this rather than on your own clock."
                    }
                }
            },
            "BuyerAccept": {
                "type": "object",
                "properties": {
                    "note": {
                        "type": "string",
                        "maxLength": 255
                    }
                }
            },
            "BuyerReject": {
                "type": "object",
                "required": [
                    "reason"
                ],
                "properties": {
                    "reason": {
                        "type": "string",
                        "maxLength": 255,
                        "description": "Required, and passed on to the supplier and the tax service."
                    }
                }
            },
            "BuyerResponse": {
                "type": "object",
                "properties": {
                    "uid": {
                        "type": "string"
                    },
                    "buyer_response": {
                        "type": "string",
                        "enum": [
                            "accepted",
                            "rejected"
                        ]
                    },
                    "responded_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            },
            "Operator": {
                "type": "object",
                "properties": {
                    "operator_code": {
                        "type": "string",
                        "description": "What goes in X-Operator-Code."
                    },
                    "legal_name": {
                        "type": "string"
                    },
                    "trading_name": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string"
                    },
                    "vertical": {
                        "type": "string",
                        "description": "The trade it is registered in — it decides which charge categories are valid."
                    },
                    "state": {
                        "type": "string"
                    },
                    "premises": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "id": {
                                    "type": "integer"
                                },
                                "name": {
                                    "type": "string"
                                },
                                "state": {
                                    "type": "string"
                                }
                            }
                        }
                    },
                    "granted_scopes": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        },
                        "description": "What this business has actually granted you, which may be narrower than your key."
                    }
                }
            },
            "EInvoicingReadiness": {
                "type": "object",
                "properties": {
                    "ready": {
                        "type": "boolean",
                        "description": "True only when a credential resolves for this business in THIS environment."
                    },
                    "environment": {
                        "type": "string",
                        "enum": [
                            "sandbox",
                            "live"
                        ]
                    },
                    "reason": {
                        "type": "string",
                        "description": "When ready is false: what has to happen, in words, because the fix is always somebody's action."
                    },
                    "source": {
                        "type": "string",
                        "description": "Whose credential would be used."
                    }
                }
            },
            "LinkRequest": {
                "type": "object",
                "required": [
                    "operator_code"
                ],
                "properties": {
                    "operator_code": {
                        "type": "string",
                        "description": "The business you are asking. It is on their own dashboard."
                    },
                    "scopes": {
                        "type": "array",
                        "items": {
                            "type": "string",
                            "enum": [
                                "invoices:read",
                                "invoices:write",
                                "credit_notes:read",
                                "credit_notes:write",
                                "customers:read",
                                "customers:write",
                                "documents:read",
                                "operators:read",
                                "levy:read",
                                "webhooks:manage"
                            ]
                        },
                        "description": "What you are asking for. They may grant less; they can never grant more than your key holds."
                    },
                    "note": {
                        "type": "string",
                        "maxLength": 255,
                        "description": "Shown to the business with the request."
                    }
                }
            },
            "LinkRequestResult": {
                "type": "object",
                "properties": {
                    "status": {
                        "type": "string",
                        "enum": [
                            "invited",
                            "active"
                        ],
                        "description": "\"invited\" until somebody at that business accepts."
                    },
                    "operator_code": {
                        "type": "string"
                    },
                    "expires_at": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When an unaccepted request lapses and has to be raised again."
                    }
                }
            },
            "Tariff": {
                "type": "object",
                "properties": {
                    "version": {
                        "type": "string"
                    },
                    "effective_from": {
                        "type": "string",
                        "format": "date"
                    },
                    "default_bp": {
                        "type": "integer",
                        "description": "The levy rate in basis points. 100 = 1%."
                    },
                    "cells": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "vertical": {
                                    "type": "string"
                                },
                                "charge_category": {
                                    "type": "string"
                                },
                                "state": {
                                    "type": "string"
                                },
                                "rate_bp": {
                                    "type": "integer"
                                }
                            }
                        },
                        "description": "Published by CODE, never by our primary keys. \"*\" in a dimension means every value of it."
                    }
                }
            },
            "ChargeCategories": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "code": {
                                    "type": "string"
                                },
                                "label": {
                                    "type": "string"
                                },
                                "tdc_eligible": {
                                    "type": "boolean"
                                },
                                "common": {
                                    "type": "boolean",
                                    "description": "True for the ones this trade uses most — put these on the first screen of the till."
                                }
                            }
                        }
                    }
                }
            },
            "ResourceList": {
                "type": "object",
                "properties": {
                    "kind": {
                        "type": "string"
                    },
                    "environment": {
                        "type": "string",
                        "enum": [
                            "sandbox",
                            "live"
                        ]
                    },
                    "data": {
                        "type": "array",
                        "items": {
                            "type": "object"
                        }
                    }
                }
            },
            "Fx": {
                "type": "object",
                "properties": {
                    "tax_currency": {
                        "type": "string",
                        "default": "NGN"
                    },
                    "rule": {
                        "type": "string",
                        "description": "What a document in another currency must carry."
                    },
                    "precision": {
                        "type": "integer"
                    },
                    "accepted_currencies": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "published_rates": {
                        "type": "array",
                        "items": {
                            "type": "object"
                        },
                        "description": "Only rates the Revenue Service has actually published. Empty means none — not zero."
                    }
                }
            },
            "Remittance": {
                "type": "object",
                "properties": {
                    "reference": {
                        "type": "string"
                    },
                    "object": {
                        "type": "string",
                        "const": "remittance"
                    },
                    "period": {
                        "type": "string",
                        "description": "YYYY-MM."
                    },
                    "status": {
                        "type": "string"
                    },
                    "due_date": {
                        "type": "string",
                        "format": "date"
                    },
                    "amounts": {
                        "type": "object",
                        "properties": {
                            "levy": {
                                "type": "integer",
                                "format": "int64",
                                "description": "The levy billed for the period. In kobo."
                            },
                            "paid": {
                                "type": "integer",
                                "format": "int64",
                                "description": "What has landed. In kobo."
                            },
                            "outstanding": {
                                "type": "integer",
                                "format": "int64",
                                "description": "What is left. In kobo."
                            }
                        }
                    },
                    "paid_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    }
                }
            },
            "RemittanceList": {
                "type": "object",
                "properties": {
                    "object": {
                        "type": "string",
                        "const": "list"
                    },
                    "data": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Remittance"
                        }
                    },
                    "page": {
                        "type": "integer"
                    },
                    "per_page": {
                        "type": "integer"
                    },
                    "count": {
                        "type": "integer",
                        "description": "Rows on THIS page."
                    },
                    "has_more": {
                        "type": "boolean",
                        "description": "Page again while this is true."
                    }
                }
            },
            "PayRequest": {
                "type": "object",
                "properties": {
                    "channel": {
                        "type": "string",
                        "description": "How the business intends to pay, e.g. transfer."
                    }
                }
            },
            "PaymentInstruction": {
                "type": "object",
                "properties": {
                    "reference": {
                        "type": "string",
                        "description": "The payment reference. It does not change between calls: the business may already have typed it into its banking app."
                    },
                    "account_name": {
                        "type": "string"
                    },
                    "account_number": {
                        "type": "string"
                    },
                    "bank": {
                        "type": "string"
                    },
                    "amount": {
                        "type": "integer",
                        "format": "int64",
                        "description": "What to pay. In kobo."
                    },
                    "expires_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    }
                }
            },
            "MandateCreate": {
                "type": "object",
                "required": [
                    "bank_code",
                    "account_number",
                    "account_name",
                    "consent_evidence"
                ],
                "properties": {
                    "bank_code": {
                        "type": "string"
                    },
                    "account_number": {
                        "type": "string",
                        "description": "Only the masked account is stored; later collections go through the mandate reference."
                    },
                    "account_name": {
                        "type": "string"
                    },
                    "consent_evidence": {
                        "type": "string",
                        "description": "Required. What the business signed, and when."
                    }
                }
            },
            "Mandate": {
                "type": "object",
                "properties": {
                    "reference": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string"
                    },
                    "account_masked": {
                        "type": "string"
                    },
                    "bank": {
                        "type": "string"
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            },
            "TicketBulk": {
                "type": "object",
                "required": [
                    "rows"
                ],
                "properties": {
                    "rows": {
                        "type": "array",
                        "minItems": 1,
                        "items": {
                            "type": "object",
                            "required": [
                                "premises_id",
                                "ticket_type",
                                "qty",
                                "unit_price"
                            ],
                            "properties": {
                                "premises_id": {
                                    "type": "integer"
                                },
                                "ticket_type": {
                                    "type": "string"
                                },
                                "qty": {
                                    "type": "integer",
                                    "minimum": 1
                                },
                                "unit_price": {
                                    "type": "integer",
                                    "format": "int64",
                                    "description": "Price of one admission. In kobo."
                                },
                                "device_code": {
                                    "type": "string",
                                    "description": "Which gate device took it."
                                },
                                "sold_at": {
                                    "type": "string",
                                    "description": "When the tap happened, for a gate that was offline."
                                }
                            }
                        }
                    }
                }
            },
            "TicketBulkResult": {
                "type": "object",
                "properties": {
                    "accepted": {
                        "type": "integer"
                    },
                    "rejected": {
                        "type": "integer"
                    },
                    "groups": {
                        "type": "array",
                        "items": {
                            "type": "object"
                        },
                        "description": "Per premises-day and ticket type, with the reason for anything refused."
                    }
                }
            },
            "Daysheets": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "array",
                        "items": {
                            "type": "object",
                            "properties": {
                                "premises_id": {
                                    "type": "integer"
                                },
                                "business_date": {
                                    "type": "string",
                                    "format": "date"
                                },
                                "status": {
                                    "type": "string",
                                    "enum": [
                                        "open",
                                        "closed"
                                    ]
                                },
                                "admissions": {
                                    "type": "integer"
                                },
                                "gross": {
                                    "type": "integer",
                                    "format": "int64",
                                    "description": "Taken so far. In kobo."
                                },
                                "document_uid": {
                                    "type": "string",
                                    "description": "The day-sheet document, once the day is closed."
                                }
                            }
                        }
                    },
                    "running_total": {
                        "type": "object",
                        "description": "Present when ?premises_id was given."
                    }
                }
            },
            "Webhook": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "url": {
                        "type": "string",
                        "format": "uri"
                    },
                    "mode": {
                        "type": "string",
                        "enum": [
                            "live",
                            "test"
                        ]
                    },
                    "events": {
                        "type": "array",
                        "items": {
                            "type": "string"
                        }
                    },
                    "description": {
                        "type": "string"
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "active",
                            "paused",
                            "failing",
                            "disabled"
                        ]
                    },
                    "consecutive_failures": {
                        "type": "integer"
                    },
                    "last_success_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "last_failure_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "created_at": {
                        "type": "string",
                        "format": "date-time"
                    }
                }
            },
            "WebhookWithSecret": {
                "allOf": [
                    {
                        "$ref": "#/components/schemas/Webhook"
                    },
                    {
                        "type": "object",
                        "properties": {
                            "secret": {
                                "type": "string",
                                "description": "THE SIGNING SECRET, RETURNED ONCE. There is no read path that can produce it again."
                            }
                        }
                    }
                ]
            },
            "WebhookIndex": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "array",
                        "items": {
                            "$ref": "#/components/schemas/Webhook"
                        }
                    },
                    "events": {
                        "type": "array",
                        "items": {
                            "type": "object"
                        },
                        "description": "The catalogue you may subscribe to."
                    },
                    "signature": {
                        "type": "object",
                        "description": "The scheme, published beside the endpoints: header name, algorithm and what is signed."
                    },
                    "retries": {
                        "type": "object",
                        "description": "The ladder and the attempt count."
                    },
                    "limits": {
                        "type": "object"
                    }
                }
            },
            "WebhookCreate": {
                "type": "object",
                "required": [
                    "url",
                    "events"
                ],
                "properties": {
                    "url": {
                        "type": "string",
                        "format": "uri",
                        "description": "HTTPS, publicly resolvable. Private, loopback and link-local addresses are refused."
                    },
                    "events": {
                        "type": "array",
                        "minItems": 1,
                        "items": {
                            "type": "string"
                        },
                        "description": "Names from the catalogue, a family such as \"invoice.*\", or \"*\"."
                    },
                    "mode": {
                        "type": "string",
                        "enum": [
                            "live",
                            "test"
                        ],
                        "default": "test",
                        "description": "A test endpoint hears sandbox facts only; a live endpoint hears live ones only."
                    },
                    "description": {
                        "type": "string",
                        "maxLength": 255
                    }
                }
            },
            "WebhookTest": {
                "type": "object",
                "required": [
                    "endpoint_id"
                ],
                "properties": {
                    "endpoint_id": {
                        "type": "integer",
                        "description": "Which of your endpoints to ping."
                    }
                }
            },
            "Delivery": {
                "type": "object",
                "properties": {
                    "id": {
                        "type": "integer"
                    },
                    "endpoint_id": {
                        "type": "integer"
                    },
                    "event": {
                        "type": "string"
                    },
                    "event_id": {
                        "type": "string",
                        "description": "The identity of the FACT. Deduplicate on this."
                    },
                    "status": {
                        "type": "string",
                        "enum": [
                            "pending",
                            "delivering",
                            "delivered",
                            "failed",
                            "dead"
                        ]
                    },
                    "attempts": {
                        "type": "integer"
                    },
                    "response_code": {
                        "type": "integer"
                    },
                    "next_attempt_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    },
                    "delivered_at": {
                        "type": [
                            "string",
                            "null"
                        ],
                        "format": "date-time"
                    }
                }
            },
            "Deleted": {
                "type": "object",
                "properties": {
                    "deleted": {
                        "type": "boolean"
                    },
                    "id": {
                        "type": "integer"
                    }
                }
            },
            "Binary": {
                "type": "string",
                "format": "binary"
            }
        },
        "responses": {
            "E400": {
                "description": "The request could not be read: no Idempotency-Key, an unusable one, or a body that is not JSON.",
                "headers": [],
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "E401": {
                "description": "The credential is missing, malformed, revoked or expired.",
                "headers": [],
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "E403": {
                "description": "The credential is right and the answer is still no: a missing scope, a business that has not granted access, a suspended vendor, or live traffic from an account that is not live yet.",
                "headers": [],
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "E404": {
                "description": "No such resource for this business. A document belonging to somebody else is 404, never 403.",
                "headers": [],
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "E409": {
                "description": "A conflict: the resource is not in a state that allows this, the first request carrying this Idempotency-Key is still running, or a document with that external reference already exists — in which case the answer names it.",
                "headers": {
                    "Retry-After": {
                        "description": "Seconds to wait before retrying.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "E415": {
                "description": "Send the body as application/json.",
                "headers": [],
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "E422": {
                "description": "Understood and refused: a field is wrong (see error.fields), or this Idempotency-Key was already used with a different body. Nothing was issued.",
                "headers": [],
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "E429": {
                "description": "Too many requests, or too many failed authentication attempts from this address. Retry-After says when.",
                "headers": {
                    "Retry-After": {
                        "description": "Seconds to wait before retrying.",
                        "schema": {
                            "type": "integer"
                        }
                    }
                },
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            },
            "E500": {
                "description": "Something went wrong at our end. Quote request_id.",
                "headers": [],
                "content": {
                    "application/json": {
                        "schema": {
                            "$ref": "#/components/schemas/Error"
                        }
                    }
                }
            }
        }
    },
    "x-scopes": [
        {
            "scope": "invoices:read",
            "means": "Read the invoices this business has issued.",
            "default": true
        },
        {
            "scope": "invoices:write",
            "means": "Issue, credit and correct fiscal invoices in this business's name.",
            "default": true
        },
        {
            "scope": "credit_notes:read",
            "means": "Read credit notes.",
            "default": false
        },
        {
            "scope": "credit_notes:write",
            "means": "Issue credit notes against this business's invoices.",
            "default": false
        },
        {
            "scope": "customers:read",
            "means": "Read the buyer records this business holds.",
            "default": false
        },
        {
            "scope": "customers:write",
            "means": "Create and correct buyer records.",
            "default": false
        },
        {
            "scope": "documents:read",
            "means": "Read fiscal documents this business has received from its suppliers.",
            "default": true
        },
        {
            "scope": "operators:read",
            "means": "Read this business's own registered particulars and its reference data.",
            "default": true
        },
        {
            "scope": "levy:read",
            "means": "Read the levy accrued and what is owed.",
            "default": false
        },
        {
            "scope": "webhooks:manage",
            "means": "Register and manage the endpoints platform events are delivered to.",
            "default": false
        }
    ],
    "x-events": [
        {
            "event": "invoice.signed",
            "label": "Invoice signed"
        },
        {
            "event": "invoice.confirmed",
            "label": "Invoice confirmed by NRS"
        },
        {
            "event": "invoice.accepted",
            "label": "Invoice accepted by the buyer"
        },
        {
            "event": "invoice.rejected",
            "label": "Invoice rejected"
        },
        {
            "event": "invoice.failed",
            "label": "Invoice failed to lodge"
        },
        {
            "event": "invoice.late_reported",
            "label": "Invoice reported late"
        },
        {
            "event": "remittance.issued",
            "label": "Remittance issued"
        },
        {
            "event": "remittance.paid",
            "label": "Remittance paid"
        },
        {
            "event": "remittance.overdue",
            "label": "Remittance overdue"
        },
        {
            "event": "payment.settled",
            "label": "Payment settled"
        },
        {
            "event": "payment.reversed",
            "label": "Payment reversed"
        },
        {
            "event": "penalty.issued",
            "label": "Penalty issued"
        },
        {
            "event": "notice.served",
            "label": "Notice served"
        }
    ],
    "x-limits": {
        "key_rate_per_min": 120,
        "ip_rate_per_min": 600,
        "rate_window_seconds": 60,
        "max_auth_failures": 10,
        "auth_failure_window": 900,
        "idempotency_retain_days": 7,
        "idempotency_lock_sec": 120,
        "idempotency_key_min": 8,
        "idempotency_key_max": 190,
        "max_keys_per_owner": 10,
        "max_endpoints": 10,
        "webhook_attempts": 7,
        "webhook_failure_threshold": 5,
        "webhook_disable_threshold": 20,
        "invite_ttl_hours": 168
    }
}