{
  "openapi": "3.0.3",
  "info": {
    "title": "NRS Invoice Gateway API",
    "version": "3.0.0",
    "description": "Complete public HTTP contract for the NRS Invoice Gateway. It covers Gateway-owned represented-business management and the STORED customer/invoice flow, public liveness/readiness endpoints, and every finite NRS proxy route enabled or deliberately blocked by the current route manifest. Administrator-only cache, migration, dependency-diagnostic, and recovery endpoints are intentionally excluded. Existing successful response bodies and statuses remain operation-owned: Gateway management responses keep their documented shapes, while sanitized NRS-owned 2xx responses are relayed without a Gateway envelope. Every Gateway-generated failure uses the shared RFC 9457 application/problem+json contract. gatewaySubBusinessId is the immutable Gateway identity used in paths and x-sub-business-id; firsBusinessId and nrsIdentity.nrsBusinessId identify the current versioned NRS mapping and can differ from the stable Gateway ID only after an audited migration. Caller X-Request-ID is optional correlation metadata; the Gateway-generated response X-Request-ID and Problem Details requestId are authoritative. During domain draining, authenticated reads and completion of existing STORED transmissions remain available while new mutations return 409 GW_DOMAIN_DRAINING. During process shutdown, all newly arriving non-probe requests return 503 GW_APPLICATION_DRAINING with Retry-After; liveness stays available and readiness returns 503."
  },
  "servers": [
    {
      "url": "https://{business}.invoice.tryduplo.com",
      "description": "Your approved NRS Invoice Gateway domain",
      "variables": {
        "business": {
          "default": "acme",
          "description": "The subdomain approved for your business in Duplo Dashboard"
        }
      }
    }
  ],
  "tags": [
    {
      "name": "Health",
      "description": "Unauthenticated compatibility, liveness, and readiness endpoints. Protected dependency diagnostics are not part of this public contract."
    },
    {
      "name": "Represented Businesses",
      "description": "Onboard represented businesses, rotate optional QR material, reverify versioned NRS identity, decide non-protected drift, and read identity history."
    },
    {
      "name": "Stored Invoices",
      "description": "STORED invoice integration: create or resolve a parent/state-scoped invoice customer, submit its customerId through POST /api/v1/invoice/sign on a STORED domain, read processing status, and transmit the signed invoice. Customer routes themselves are authorized by domain/API key and are not restricted by invoice-handling mode. PASSTHROUGH uses the NRS invoice document directly and does not require these customer operations."
    },
    {
      "name": "NRS Diagnostics",
      "description": "Finite unbilled NRS authentication, entity, recipient, and sender-health routes."
    },
    {
      "name": "NRS Resources",
      "description": "Finite allowlist of NRS reference-data resources."
    },
    {
      "name": "NRS Invoice Operations",
      "description": "Represented-business-bound validation, signing, lookup, and transmission operations plus explicitly blocked inbound operations."
    }
  ],
  "components": {
    "securitySchemes": {
      "apiKey": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "The API key generated for your business in Duplo Dashboard. The credential's ipWhitelisted setting is enforced end to end on the customer-facing custom-domain Gateway routes in this public contract. A trusted edge overwrites the configured client-IP header and Gateway carries that verified address over its authenticated internal hop; caller-supplied X-Forwarded-For values are never trusted. An empty IP allowlist permits any source. When an allowlist is configured, a missing, malformed, or nonmatching verified client address is rejected with HTTP 403."
      }
    },
    "parameters": {
      "CallerRequestId": {
        "name": "X-Request-ID",
        "in": "header",
        "required": false,
        "description": "Optional caller correlation metadata. Gateway creates a new authoritative request ID, returns it in the response X-Request-ID header and Problem Details requestId, and propagates that generated value to its dependencies.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128,
          "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
        },
        "example": "erp-run-20260916-0042"
      },
      "IdempotencyKey": {
        "name": "x-idempotency-key",
        "in": "header",
        "required": true,
        "description": "Stable key identifying one logical command. Gateway management keys contain 8–128 letters, digits, dots, underscores, colons, or hyphens. For onboarding, the key binds the normalized optional profile; a completed replay may omit NRS credentials and QR material.",
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 128,
          "pattern": "^[A-Za-z0-9._:-]+$"
        },
        "example": "command-acme-retail-0001"
      },
      "Page": {
        "name": "page",
        "in": "query",
        "required": false,
        "description": "One-based result page.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 1000000,
          "default": 1
        }
      },
      "Limit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "description": "Maximum represented businesses returned on one page.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 50
        }
      },
      "GatewaySubBusinessId": {
        "name": "gatewaySubBusinessId",
        "in": "path",
        "required": true,
        "description": "Immutable Gateway represented-business identifier returned by onboarding/list. Treat it as an opaque value; it may be an original NRS ID or a retained compatibility alias and can differ from the current versioned NRS mapping after an audited migration.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        },
        "example": "nrs-business-demo"
      },
      "InvoiceId": {
        "name": "invoiceId",
        "in": "path",
        "required": true,
        "description": "Gateway/STORED invoice canonical UUID version 4.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89aAbB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
        }
      },
      "ReviewId": {
        "name": "reviewId",
        "in": "path",
        "required": true,
        "description": "Identity-review UUID returned by reverification/history.",
        "schema": {
          "type": "string",
          "format": "uuid",
          "pattern": "^[0-9a-fA-F-]{36}$"
        }
      },
      "EntityId": {
        "name": "entityId",
        "in": "path",
        "required": true,
        "description": "NRS entity identifier (1-128 allowlisted identifier characters).",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 128,
          "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
        }
      },
      "Tin": {
        "name": "tin",
        "in": "path",
        "required": true,
        "description": "Recipient taxpayer identifier accepted by the NRS lookup route.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 64,
          "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
        }
      },
      "Irn": {
        "name": "irn",
        "in": "path",
        "required": true,
        "description": "Invoice reference number bound to the represented business.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200,
          "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
        }
      },
      "NrsResource": {
        "name": "resource",
        "in": "path",
        "required": true,
        "description": "One resource explicitly enabled by the Gateway route manifest.",
        "schema": {
          "type": "string",
          "enum": [
            "tax-categories",
            "vat-exemptions",
            "hs-codes",
            "services-codes",
            "invoice-types",
            "invoice-quantity-codes",
            "payment_means",
            "currencies",
            "countries",
            "states",
            "lgas"
          ]
        }
      },
      "SubBusinessId": {
        "name": "x-sub-business-id",
        "in": "header",
        "required": true,
        "description": "Immutable gatewaySubBusinessId returned by onboarding/list. Gateway resolves it to the current audited NRS identity before dispatch.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 255
        }
      },
      "OptionalLegacyIdempotencyKey": {
        "name": "x-idempotency-key",
        "in": "header",
        "required": false,
        "description": "Optional in the current PASSTHROUGH API version. When supplied, use 8-128 allowlisted characters and preserve the same key for the same logical mutation. STORED sign requires this header.",
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 128,
          "pattern": "^[A-Za-z0-9._:-]+$"
        }
      },
      "OptionalStandardIdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "description": "Optional standard spelling for PASSTHROUGH transmit. Do not send both spellings with different values.",
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 128,
          "pattern": "^[A-Za-z0-9._:-]+$"
        }
      },
      "AttemptNumber": {
        "name": "x-attempt-number",
        "in": "header",
        "required": false,
        "description": "Positive safe integer for a PASSTHROUGH sign attempt; defaults to 1. Keep it stable with one logical idempotency identity.",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 9007199254740991,
          "default": 1
        }
      },
      "InvoiceReference": {
        "name": "x-invoice-reference",
        "in": "header",
        "required": false,
        "description": "Optional defensive copy of the request body's irn. When supplied it must match exactly.",
        "schema": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200,
          "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$"
        }
      },
      "InvoicePage": {
        "name": "page",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 1000000,
          "default": 1
        }
      },
      "InvoiceLimit": {
        "name": "limit",
        "in": "query",
        "required": false,
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 20
        }
      },
      "FirsStatus": {
        "name": "firsStatus",
        "in": "query",
        "required": false,
        "description": "Optional exact regulator-processing status filter.",
        "schema": {
          "type": "string",
          "enum": [
            "submitted",
            "signed",
            "approved",
            "rejected",
            "pending",
            "validated"
          ]
        }
      }
    },
    "schemas": {
      "NrsCryptoKeys": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "certificate",
          "publicKey"
        ],
        "description": "Optional, all-or-nothing NRS QR material. Gateway treats both values as opaque, stores them exactly as supplied, and does not parse a certificate, check dates, normalize the strings, measure RSA key size, or verify a key match. The QR generator interprets the values only when QR generation is attempted. A privateKey property is not supported.",
        "properties": {
          "certificate": {
            "type": "string",
            "minLength": 1,
            "description": "Non-blank NRS-issued certificate value embedded in the QR payload. Maximum size: 32 KiB as UTF-8.",
            "example": "nrs-issued-certificate-value"
          },
          "publicKey": {
            "type": "string",
            "minLength": 1,
            "description": "Non-blank NRS public-key value used only during QR generation. The runtime QR generator accepts plain PEM or base64-encoded PEM. Maximum size: 16 KiB as UTF-8.",
            "example": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n"
          }
        }
      },
      "NrsIdentity": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "entityId",
          "entityReference",
          "nrsBusinessId",
          "businessName",
          "tin",
          "irnTemplate"
        ],
        "description": "Current versioned NRS identity snapshot. nrsBusinessId and firsBusinessId are the current external mapping; gatewaySubBusinessId remains the immutable Gateway identity.",
        "properties": {
          "entityId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "NRS entity_id returned by successful authentication."
          },
          "entityReference": {
            "type": "string",
            "nullable": true,
            "minLength": 1,
            "maxLength": 255,
            "description": "Optional NRS entity reference, with the selected business reference used as a fallback when the entity reference was absent. Null when neither bounded value was available. This opaque value is not used for invoice routing."
          },
          "nrsBusinessId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Current NRS business ID. Initially this normally equals gatewaySubBusinessId, but an audited protected migration can advance this mapping without changing the stable Gateway ID."
          },
          "businessName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Registered name of the selected NRS business at onboarding time."
          },
          "tin": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "TIN of the selected NRS business at onboarding time."
          },
          "irnTemplate": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "NRS IRN template of the selected business at onboarding time."
          }
        }
      },
      "RepresentedBusinessProfile": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "legalName",
          "email",
          "phoneNumber",
          "invoiceNumberPrefix"
        ],
        "description": "Optional local profile values supplied by the integrator during onboarding. They are not NRS-verified identity fields.",
        "properties": {
          "name": {
            "type": "string",
            "nullable": true,
            "maxLength": 50
          },
          "legalName": {
            "type": "string",
            "nullable": true,
            "maxLength": 50
          },
          "email": {
            "type": "string",
            "nullable": true,
            "format": "email",
            "maxLength": 254
          },
          "phoneNumber": {
            "type": "string",
            "nullable": true,
            "maxLength": 20
          },
          "invoiceNumberPrefix": {
            "type": "string",
            "nullable": true,
            "maxLength": 32
          }
        }
      },
      "RepresentedBusinessCryptoSummary": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "configured",
          "version",
          "updatedAt"
        ],
        "description": "Safe metadata about optional NRS QR material. Certificate and public-key values are never returned.",
        "properties": {
          "configured": {
            "type": "boolean",
            "description": "True when an NRS certificate and public-key pair is stored."
          },
          "version": {
            "type": "integer",
            "minimum": 0,
            "description": "Zero before QR material is stored; incremented by successful storage or replacement."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true,
            "description": "Time the current QR-material version was stored, or null when it has never been configured."
          }
        }
      },
      "RepresentedBusinessInfo": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "gatewaySubBusinessId",
          "onboardingIntentId",
          "domain",
          "businessState",
          "modeVersion",
          "status",
          "profile",
          "firsBusinessId",
          "nrsIdentity",
          "crypto",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "gatewaySubBusinessId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Immutable Gateway represented-business identity used in paths and x-sub-business-id. Treat it as opaque; use nrsIdentity.nrsBusinessId as the current NRS invoice business_id after any audited migration."
          },
          "onboardingIntentId": {
            "type": "string",
            "format": "uuid",
            "description": "The onboarding intent that created this represented-business mapping."
          },
          "domain": {
            "type": "string",
            "minLength": 1,
            "maxLength": 15,
            "description": "Approved Gateway domain label to which this mapping belongs."
          },
          "businessState": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ],
            "description": "NRS environment state to which this mapping is bound."
          },
          "modeVersion": {
            "type": "integer",
            "minimum": 1,
            "description": "Approved domain mode version currently bound to this active mapping."
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "disabled"
            ],
            "description": "Current mapped NRS activity state. Disabled identities remain visible for audit/history but cannot authorize invoice operations."
          },
          "profile": {
            "$ref": "#/components/schemas/RepresentedBusinessProfile"
          },
          "firsBusinessId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Backward-compatible name for the current versioned NRS business ID. It equals nrsIdentity.nrsBusinessId, but can differ from immutable gatewaySubBusinessId after an audited migration."
          },
          "nrsIdentity": {
            "$ref": "#/components/schemas/NrsIdentity"
          },
          "crypto": {
            "$ref": "#/components/schemas/RepresentedBusinessCryptoSummary"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time",
            "description": "Time the represented-business mapping was created."
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time",
            "description": "Time the stored mapping was last updated; this is not proof of a fresh NRS lookup."
          }
        }
      },
      "RepresentedBusinessPagination": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "page",
          "limit",
          "total",
          "totalPages"
        ],
        "properties": {
          "page": {
            "type": "integer",
            "minimum": 1
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          },
          "total": {
            "type": "integer",
            "minimum": 0,
            "description": "Total active represented businesses in the current parent/domain/state/current-mode scope."
          },
          "totalPages": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "RepresentedBusinessList": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "items",
          "pagination"
        ],
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RepresentedBusinessInfo"
            }
          },
          "pagination": {
            "$ref": "#/components/schemas/RepresentedBusinessPagination"
          }
        }
      },
      "ProblemViolation": {
        "type": "object",
        "required": [
          "location",
          "code",
          "detail"
        ],
        "properties": {
          "location": {
            "type": "string",
            "enum": [
              "header",
              "path",
              "query",
              "body"
            ]
          },
          "field": {
            "type": "string",
            "description": "Canonical header, path, or query field name. The rejected value is never returned."
          },
          "pointer": {
            "type": "string",
            "description": "RFC 6901 JSON Pointer for a body violation. The rejected value is never returned."
          },
          "code": {
            "type": "string",
            "enum": [
              "REQUIRED",
              "FORMAT",
              "TYPE",
              "RANGE",
              "LENGTH",
              "UNKNOWN_FIELD",
              "MISMATCH",
              "IMMUTABLE_FIELD"
            ]
          },
          "detail": {
            "type": "string",
            "maxLength": 256
          }
        }
      },
      "ProblemAction": {
        "type": "object",
        "required": [
          "code",
          "description",
          "documentation"
        ],
        "properties": {
          "code": {
            "type": "string",
            "description": "Stable corrective-action identifier."
          },
          "description": {
            "type": "string",
            "description": "Plain-language action the integrating partner should take."
          },
          "documentation": {
            "type": "string",
            "format": "uri",
            "description": "Canonical documentation for the stable Gateway error code."
          }
        }
      },
      "ProblemRetry": {
        "type": "object",
        "required": [
          "strategy"
        ],
        "properties": {
          "strategy": {
            "type": "string",
            "enum": [
              "DO_NOT_RETRY",
              "AFTER_CORRECTION",
              "BACKOFF",
              "SAME_IDEMPOTENCY_KEY",
              "POLL_OPERATION",
              "CONTACT_SUPPORT"
            ]
          },
          "sameIdempotencyKey": {
            "type": "boolean",
            "description": "When true, a permitted retry must retain the original idempotency key and logically identical content."
          },
          "afterSeconds": {
            "type": "integer",
            "minimum": 0,
            "maximum": 86400,
            "description": "Delay before a permitted retry. The Retry-After header takes precedence."
          }
        }
      },
      "ProblemDetails": {
        "type": "object",
        "description": "RFC 9457 Problem Details plus stable Duplo action, retry, validation, and correlation extensions. English text is not a machine contract; branch on code and retry.strategy.",
        "required": [
          "type",
          "title",
          "status",
          "detail",
          "instance",
          "code",
          "requestId",
          "timestamp",
          "action",
          "retry",
          "message",
          "statusCode",
          "path"
        ],
        "properties": {
          "type": {
            "type": "string",
            "format": "uri",
            "description": "Stable error-type URI under https://docs.tryduplo.com/invoicing/nrs/errors/{code}."
          },
          "title": {
            "type": "string",
            "description": "Stable, safe summary. Do not parse this text."
          },
          "status": {
            "type": "integer",
            "minimum": 400,
            "maximum": 599
          },
          "detail": {
            "type": "string",
            "maxLength": 512,
            "description": "Safe occurrence detail. It never contains secrets, stacks, provider bodies, or internal topology."
          },
          "instance": {
            "type": "string",
            "format": "uri",
            "description": "Opaque occurrence identifier in urn:duplo:request:{requestId} form."
          },
          "code": {
            "type": "string",
            "description": "Immutable machine-readable Gateway error code.",
            "enum": [
              "GW_REQUEST_INVALID_JSON",
              "GW_REQUEST_BODY_INCOMPLETE",
              "GW_REQUEST_BODY_TIMEOUT",
              "GW_REQUEST_VALIDATION_FAILED",
              "GW_REQUEST_PATH_PARAMETER_INVALID",
              "GW_REQUEST_HEADER_INVALID",
              "GW_REQUEST_SERVER_FIELD_SUPPLIED",
              "GW_REQUEST_BODY_TOO_LARGE",
              "GW_REQUEST_URI_TOO_LONG",
              "GW_REQUEST_MEDIA_TYPE_UNSUPPORTED",
              "GW_ROUTE_NOT_FOUND",
              "GW_METHOD_NOT_ALLOWED",
              "GW_RATE_LIMIT_EXCEEDED",
              "GW_GATEWAY_CAPACITY_EXCEEDED",
              "GW_ROUTING_LOOP_DETECTED",
              "GW_EDGE_VERIFICATION_FAILED",
              "GW_AUTH_API_KEY_REQUIRED",
              "GW_API_KEY_INVALID",
              "GW_AUTH_TENANT_FORBIDDEN",
              "GW_AUTH_CONTEXT_UNAVAILABLE",
              "GW_ADMIN_AUTHENTICATION_FAILED",
              "GW_DOMAIN_NOT_PROVISIONED",
              "GW_DOMAIN_DRAINING",
              "GW_APPLICATION_DRAINING",
              "GW_DOMAIN_REGISTRY_UNAVAILABLE",
              "GW_TENANT_AUTHORIZATION_UNAVAILABLE",
              "GW_DOMAIN_APPROVAL_STATE_CHANGED",
              "GW_TENANT_MODE_UNAVAILABLE",
              "GW_OPERATION_MODE_CONFLICT",
              "GW_REGULATOR_UNAVAILABLE",
              "GW_INVOICE_OPERATION_UNAVAILABLE",
              "GW_SUB_BUSINESS_ID_REQUIRED",
              "GW_SUB_BUSINESS_ID_INVALID",
              "GW_SUB_BUSINESS_NOT_FOUND",
              "GW_SUB_BUSINESS_FORBIDDEN",
              "GW_INVOICE_IRN_INVALID",
              "GW_INVOICE_IRN_FORBIDDEN",
              "GW_INVOICE_BUSINESS_MISMATCH",
              "GW_INVOICE_SUPPLIER_TIN_MISMATCH",
              "GW_INVOICE_REFERENCE_MISMATCH",
              "GW_INVOICE_TRANSMIT_BODY_NOT_EMPTY",
              "GW_IDEMPOTENCY_KEY_REQUIRED",
              "GW_IDEMPOTENCY_KEY_INVALID",
              "GW_IDEMPOTENCY_CONTENT_CONFLICT",
              "GW_ATTEMPT_NUMBER_INVALID",
              "GW_BILLING_WALLET_DECLINED",
              "GW_BILLING_ATTEMPT_CONFLICT",
              "GW_BILLING_REQUEST_REJECTED",
              "GW_BILLING_SERVICE_UNAVAILABLE",
              "GW_SIGN_ATTEMPT_ALREADY_PROCESSED",
              "GW_SIGN_RECOVERY_UNAVAILABLE",
              "GW_SIGN_REJECTED",
              "GW_SIGN_REVERSAL_UNCONFIRMED",
              "GW_SIGN_OUTCOME_UNCONFIRMED",
              "GW_TRANSMIT_ATTEMPT_ALREADY_PROCESSED",
              "GW_TRANSMIT_OUTCOME_UNCONFIRMED",
              "GW_OPERATION_NOT_FOUND",
              "GW_INVOICE_INTAKE_UNAVAILABLE",
              "GW_INVOICE_NOT_FOUND",
              "GW_INVOICE_STATE_CONFLICT",
              "GW_INVOICE_NOT_TRANSMITTABLE",
              "GW_MANAGEMENT_SERVICE_UNAVAILABLE",
              "GW_UPSTREAM_RESPONSE_INVALID",
              "GW_ONBOARDING_NOT_RESUMABLE",
              "GW_NRS_CREDENTIALS_REQUIRED",
              "GW_ATTESTATION_SERVICE_UNAVAILABLE",
              "GW_NRS_VERIFICATION_UNAVAILABLE",
              "GW_NRS_LOGIN_INVALID",
              "GW_NRS_APPLICATION_NOT_LINKED",
              "GW_NRS_CREDENTIALS_REJECTED",
              "GW_NRS_AUTH_RESPONSE_INVALID",
              "GW_NRS_AUTH_UNAVAILABLE",
              "GW_NRS_ENTITY_NOT_FOUND",
              "GW_NRS_ENTITY_INACTIVE",
              "GW_NRS_ENTITY_METADATA_UNSUPPORTED",
              "GW_NRS_ACTIVE_BUSINESS_NOT_FOUND",
              "GW_NRS_BUSINESS_INACTIVE",
              "GW_NRS_BUSINESS_TIN_NOT_FOUND",
              "GW_NRS_BUSINESS_SELECTION_AMBIGUOUS",
              "GW_NRS_BUSINESS_METADATA_INVALID",
              "GW_NRS_IRN_TEMPLATE_MISSING",
              "GW_ONBOARDING_SERVICE_INVALID_RESPONSE",
              "GW_CRYPTO_MATERIAL_SERVICE_INVALID_RESPONSE",
              "GW_IDENTITY_REVIEW_CONFLICT",
              "GW_IDENTITY_PROTECTED_MIGRATION_REQUIRED",
              "GW_IDENTITY_REVIEW_NOT_FOUND",
              "GW_IDENTITY_SERVICE_INVALID_RESPONSE",
              "GW_UPSTREAM_TIMEOUT",
              "GW_UPSTREAM_UNAVAILABLE",
              "GW_INTERNAL_ERROR",
              "GW_CUSTOMER_NOT_FOUND",
              "GW_CUSTOMER_ALREADY_EXISTS"
            ]
          },
          "requestId": {
            "type": "string",
            "format": "uuid",
            "description": "Gateway-generated correlation ID also returned in X-Request-ID."
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          },
          "action": {
            "$ref": "#/components/schemas/ProblemAction"
          },
          "retry": {
            "$ref": "#/components/schemas/ProblemRetry"
          },
          "errors": {
            "type": "array",
            "maxItems": 20,
            "items": {
              "$ref": "#/components/schemas/ProblemViolation"
            }
          },
          "operationId": {
            "type": "string",
            "maxLength": 128,
            "pattern": "^[A-Za-z0-9._:-]+$",
            "description": "Public operation identifier for polling an asynchronous or ambiguous outcome."
          },
          "message": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated alias of detail."
          },
          "statusCode": {
            "type": "integer",
            "deprecated": true,
            "description": "Deprecated alias of status."
          },
          "path": {
            "type": "string",
            "deprecated": true,
            "description": "Deprecated request path without query values."
          }
        }
      },
      "NrsCredentials": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "email",
          "password"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 254
          },
          "password": {
            "type": "string",
            "format": "password",
            "minLength": 1,
            "maxLength": 1024
          }
        }
      },
      "NrsDirectAuthenticationRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "email",
          "password"
        ],
        "properties": {
          "email": {
            "type": "string",
            "format": "email",
            "minLength": 3,
            "maxLength": 254
          },
          "password": {
            "type": "string",
            "format": "password",
            "minLength": 1,
            "maxLength": 256
          }
        }
      },
      "NrsOpaqueResponse": {
        "description": "NRS-owned response. Gateway preserves successful body bytes and does not promise fields beyond the relevant NRS contract."
      },
      "NrsInvoiceDocument": {
        "type": "object",
        "additionalProperties": true,
        "description": "Regulator-owned NRS invoice payload. For PASSTHROUGH sign/validate, business_id must equal the represented business's current nrsIdentity.nrsBusinessId and accounting_supplier_party.tin must match the current verified TIN.",
        "properties": {
          "irn": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "business_id": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "accounting_supplier_party": {
            "type": "object",
            "additionalProperties": true,
            "properties": {
              "tin": {
                "type": "string",
                "minLength": 1,
                "maxLength": 255
              }
            }
          }
        }
      },
      "PassthroughInvoiceSignInput": {
        "description": "PASSTHROUGH request selected when the approved domain mode is PASSTHROUGH. Gateway verifies the IRN and represented-business identity before forwarding the regulator-owned document to NRS.",
        "allOf": [
          {
            "$ref": "#/components/schemas/NrsInvoiceDocument"
          },
          {
            "type": "object",
            "required": [
              "irn",
              "business_id",
              "accounting_supplier_party"
            ],
            "properties": {
              "irn": {
                "type": "string",
                "pattern": "^[A-Za-z0-9][A-Za-z0-9._:-]*$",
                "description": "Invoice reference used for the billed signing attempt. It must start with an alphanumeric character and then contain only letters, numbers, dots, underscores, colons, or hyphens."
              },
              "business_id": {
                "type": "string",
                "pattern": "^(?!\\s)(?!.*\\s$)[^\\\\\\u0000-\\u001F\\u007F]+$",
                "description": "Must exactly equal the selected represented business's current nrsIdentity.nrsBusinessId. Leading or trailing whitespace, backslashes, and control characters are rejected."
              },
              "accounting_supplier_party": {
                "type": "object",
                "required": [
                  "tin"
                ],
                "properties": {
                  "tin": {
                    "type": "string",
                    "pattern": "^(?=.*\\S)[^\\\\\\u0000-\\u001F\\u007F]+$",
                    "description": "Must match the selected represented business's current verified TIN after trimming outer whitespace and comparing case-insensitively. Backslashes and control characters are rejected."
                  }
                }
              }
            }
          }
        ]
      },
      "StoredBillingReference": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "irn",
          "issueDate"
        ],
        "properties": {
          "irn": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "Original invoice IRN."
          },
          "issueDate": {
            "type": "string",
            "format": "date",
            "description": "Original invoice issue date."
          }
        }
      },
      "StoredSupplierInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "email",
          "phoneNumber",
          "tin",
          "country",
          "address",
          "postcode"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Must match the selected represented business's current verified NRS business name after trimming, collapsing repeated whitespace, and comparing case-insensitively."
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 225
          },
          "phoneNumber": {
            "type": "string",
            "minLength": 1,
            "maxLength": 225,
            "pattern": "^[0-9+]+$"
          },
          "tin": {
            "type": "string",
            "minLength": 1,
            "maxLength": 50,
            "pattern": "^[A-Za-z0-9-]+$",
            "description": "Must match the current verified TIN of the represented business selected by x-sub-business-id."
          },
          "country": {
            "type": "string",
            "minLength": 2,
            "maxLength": 2,
            "pattern": "^[A-Z]{2}$",
            "description": "ISO 3166-1 alpha-2 country code."
          },
          "state": {
            "type": "string",
            "maxLength": 100
          },
          "city": {
            "type": "string",
            "maxLength": 100
          },
          "address": {
            "type": "string",
            "minLength": 3,
            "maxLength": 50
          },
          "postcode": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10
          }
        }
      },
      "StoredPartyInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "email",
          "phoneNumber",
          "tin",
          "country",
          "address",
          "postcode"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 225
          },
          "phoneNumber": {
            "type": "string",
            "minLength": 1,
            "maxLength": 225,
            "pattern": "^[0-9+]+$"
          },
          "tin": {
            "type": "string",
            "minLength": 1,
            "maxLength": 50,
            "pattern": "^[A-Za-z0-9-]+$"
          },
          "country": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100
          },
          "state": {
            "type": "string",
            "maxLength": 100
          },
          "city": {
            "type": "string",
            "maxLength": 100
          },
          "address": {
            "type": "string",
            "minLength": 3,
            "maxLength": 50
          },
          "postcode": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10
          }
        }
      },
      "StoredPaymentDetailsInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "accountName",
          "accountNumber"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "local",
              "international"
            ],
            "default": "local",
            "description": "Account shape. Omission is treated as local."
          },
          "accountName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200
          },
          "accountNumber": {
            "type": "string",
            "minLength": 1,
            "maxLength": 34,
            "description": "Local account number or international IBAN."
          },
          "bankName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "Required for local accounts, including when type is omitted."
          },
          "swiftCode": {
            "type": "string",
            "minLength": 1,
            "maxLength": 11,
            "description": "Required when type is international."
          },
          "bankAddress": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Required when type is international."
          },
          "routingNumber": {
            "type": "string",
            "maxLength": 50
          },
          "intermediaryBankName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 200,
            "description": "Required when type is international."
          },
          "intermediaryBankAddress": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Required when type is international."
          },
          "correspondentSwiftCode": {
            "type": "string",
            "maxLength": 11
          },
          "correspondentBankName": {
            "type": "string",
            "maxLength": 200
          },
          "additionalInformation": {
            "type": "string",
            "maxLength": 500
          }
        },
        "oneOf": [
          {
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "local"
                ]
              }
            },
            "required": [
              "bankName"
            ]
          },
          {
            "properties": {
              "type": {
                "type": "string",
                "enum": [
                  "international"
                ]
              }
            },
            "required": [
              "type",
              "swiftCode",
              "bankAddress",
              "intermediaryBankName",
              "intermediaryBankAddress"
            ]
          }
        ]
      },
      "StoredInvoiceTaxInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "rate"
        ],
        "properties": {
          "name": {
            "type": "string",
            "minLength": 1,
            "description": "Current NRS tax category code."
          },
          "rate": {
            "type": "number",
            "minimum": 0,
            "description": "Tax rate in percentage points, for example 7.5 for 7.5%."
          }
        }
      },
      "StoredInvoiceLineAdjustmentInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "valueType",
          "value"
        ],
        "properties": {
          "kind": {
            "type": "string",
            "enum": [
              "allowance",
              "charge"
            ],
            "description": "Optional explicit kind; defaults to the containing allowances or charges array."
          },
          "valueType": {
            "type": "string",
            "enum": [
              "fixed",
              "percentage"
            ]
          },
          "value": {
            "type": "number",
            "minimum": 0,
            "description": "For fixed, the monetary amount. For percentage, a decimal such as 0.1 for 10%."
          },
          "description": {
            "type": "string",
            "maxLength": 255
          }
        }
      },
      "StoredInvoiceItemInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "description",
          "unit",
          "unitPrice"
        ],
        "properties": {
          "description": {
            "type": "string",
            "minLength": 3,
            "pattern": "^(?!.*\\s{2,})[a-zA-Z0-9&\"[\\]\\s-]+$"
          },
          "unit": {
            "type": "string",
            "minLength": 1,
            "description": "Current NRS invoice quantity code."
          },
          "quantity": {
            "type": "number",
            "minimum": 0,
            "default": 1
          },
          "unitPrice": {
            "type": "number",
            "minimum": 0
          },
          "taxes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StoredInvoiceTaxInput"
            }
          },
          "allowances": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StoredInvoiceLineAdjustmentInput"
            }
          },
          "charges": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StoredInvoiceLineAdjustmentInput"
            }
          },
          "productCategory": {
            "type": "string",
            "minLength": 1,
            "pattern": ".*\\S.*"
          },
          "hsnCode": {
            "type": "string",
            "maxLength": 10,
            "pattern": "^\\d{4}\\.\\d{2}$"
          },
          "serviceCategory": {
            "type": "string",
            "minLength": 1,
            "pattern": ".*\\S.*"
          },
          "isicCode": {
            "type": "string",
            "minLength": 1,
            "maxLength": 10,
            "pattern": ".*\\S.*"
          }
        },
        "oneOf": [
          {
            "required": [
              "productCategory",
              "hsnCode"
            ],
            "not": {
              "anyOf": [
                {
                  "required": [
                    "serviceCategory"
                  ]
                },
                {
                  "required": [
                    "isicCode"
                  ]
                }
              ]
            }
          },
          {
            "required": [
              "serviceCategory",
              "isicCode"
            ],
            "not": {
              "anyOf": [
                {
                  "required": [
                    "productCategory"
                  ]
                },
                {
                  "required": [
                    "hsnCode"
                  ]
                }
              ]
            }
          }
        ]
      },
      "StoredInvoiceDiscountInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "value"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "percentage",
              "flat"
            ],
            "description": "Invoice-level discount type. Use flat, not fixed, for a monetary amount."
          },
          "value": {
            "type": "number",
            "minimum": 0,
            "description": "For percentage, use a decimal such as 0.1 for 10%."
          }
        }
      },
      "StoredInvoiceInput": {
        "type": "object",
        "additionalProperties": false,
        "description": "STORED request selected when the approved domain mode is STORED. Gateway derives domainConfigId, domain, businessState, modeVersion, and gatewaySubBusinessId from the approved host, API key, and x-sub-business-id header. Do not send those fields or businessId, parentBusinessId, or subBusinessId; Gateway rejects server-managed routing fields.",
        "required": [
          "invoiceReferenceNumber",
          "invoiceType",
          "issueDate",
          "documentCurrency",
          "taxCurrency",
          "supplierData",
          "items"
        ],
        "properties": {
          "invoiceNumber": {
            "type": "string",
            "maxLength": 100,
            "pattern": "^[A-Za-z0-9-]+$"
          },
          "invoiceReferenceNumber": {
            "type": "string",
            "minLength": 1,
            "maxLength": 100,
            "description": "Durable IRN generated for this represented business."
          },
          "invoiceType": {
            "type": "string",
            "enum": [
              "380",
              "381",
              "384",
              "385",
              "388",
              "389"
            ],
            "description": "Stored invoice type. Credit notes (380) and debit notes (384) require at least one billingReferences or billingReference entry."
          },
          "billingReferences": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/StoredBillingReference"
            }
          },
          "billingReference": {
            "type": "array",
            "minItems": 1,
            "deprecated": true,
            "description": "Legacy alias for billingReferences.",
            "items": {
              "$ref": "#/components/schemas/StoredBillingReference"
            }
          },
          "issueDate": {
            "type": "string",
            "format": "date",
            "description": "Invoice issue date; future dates are rejected."
          },
          "taxPointDate": {
            "type": "string",
            "format": "date"
          },
          "documentCurrency": {
            "type": "string",
            "enum": [
              "NGN",
              "USD",
              "EUR",
              "GBP",
              "ZAR",
              "KES"
            ]
          },
          "taxCurrency": {
            "type": "string",
            "enum": [
              "NGN",
              "USD",
              "EUR",
              "GBP",
              "ZAR",
              "KES"
            ]
          },
          "paymentStatus": {
            "type": "string",
            "enum": [
              "pending",
              "paid",
              "partially_paid",
              "overdue"
            ],
            "default": "pending"
          },
          "paymentDate": {
            "type": "string",
            "format": "date"
          },
          "supplierData": {
            "$ref": "#/components/schemas/StoredSupplierInput"
          },
          "customerId": {
            "type": "string",
            "format": "uuid",
            "description": "Existing invoice customer created or resolved through POST /customers, GET /customers, or GET /customers/{customerId} in the authenticated parent and test/live context. The customer must include the invoice module and invoice metadata with a postcode, otherwise intake is rejected. Customer creation is parent-scoped and does not receive gatewaySubBusinessId, so the same customer ID can be reused across represented businesses under that parent in the same state. A legacy customer with an existing non-null represented-business binding is accepted only for that matching gatewaySubBusinessId; the current customer API does not create or manage this legacy child scope. The invoice's represented-business identity comes only from the onboarding/list/detail gatewaySubBusinessId supplied in x-sub-business-id. Intake currently accepts omission, but customer data is operationally required for NRS readiness and no later Gateway edit attaches it; omit only if you intentionally accept later asynchronous rejection."
          },
          "payeeData": {
            "$ref": "#/components/schemas/StoredPartyInput"
          },
          "taxRepresentativeData": {
            "$ref": "#/components/schemas/StoredPartyInput"
          },
          "items": {
            "type": "array",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/StoredInvoiceItemInput"
            }
          },
          "discount": {
            "$ref": "#/components/schemas/StoredInvoiceDiscountInput"
          },
          "notes": {
            "type": "string",
            "minLength": 3,
            "maxLength": 50
          },
          "paymentTerms": {
            "type": "string",
            "minLength": 3,
            "maxLength": 50
          },
          "paymentDetails": {
            "$ref": "#/components/schemas/StoredPaymentDetailsInput"
          },
          "saveAsDraft": {
            "type": "boolean",
            "default": false,
            "deprecated": true,
            "description": "Accepted by the shared DTO but ignored by STORED intake. STORED invoices are always accepted as submitted with pending NRS status; omit this field."
          }
        },
        "allOf": [
          {
            "description": "Credit notes and debit notes require at least one current or legacy billing-reference array. Other invoice types do not.",
            "anyOf": [
              {
                "properties": {
                  "invoiceType": {
                    "enum": [
                      "381",
                      "385",
                      "388",
                      "389"
                    ]
                  }
                }
              },
              {
                "required": [
                  "billingReferences"
                ]
              },
              {
                "required": [
                  "billingReference"
                ]
              }
            ]
          }
        ]
      },
      "IdentityObserved": {
        "allOf": [
          {
            "$ref": "#/components/schemas/NrsIdentity"
          },
          {
            "type": "object",
            "required": [
              "active"
            ],
            "properties": {
              "active": {
                "type": "boolean"
              }
            }
          }
        ]
      },
      "IdentityReview": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "gatewaySubBusinessId",
          "reviewId",
          "version",
          "status",
          "driftClass",
          "changedFields",
          "requiresProtectedMigration",
          "observedIdentity"
        ],
        "properties": {
          "gatewaySubBusinessId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "reviewId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "version": {
            "type": "integer",
            "minimum": 1
          },
          "status": {
            "type": "string",
            "enum": [
              "unchanged",
              "pending_review",
              "active",
              "rejected"
            ]
          },
          "driftClass": {
            "type": "string",
            "enum": [
              "initial",
              "additive",
              "protected"
            ]
          },
          "changedFields": {
            "type": "array",
            "uniqueItems": true,
            "maxItems": 7,
            "items": {
              "type": "string",
              "enum": [
                "entityId",
                "entityReference",
                "nrsBusinessId",
                "businessName",
                "tin",
                "irnTemplate",
                "active"
              ]
            }
          },
          "requiresProtectedMigration": {
            "type": "boolean"
          },
          "observedIdentity": {
            "$ref": "#/components/schemas/IdentityObserved"
          }
        }
      },
      "IdentityVersion": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "reviewId",
          "version",
          "status",
          "driftClass",
          "changedFields",
          "observedIdentity",
          "observedAt",
          "reviewedAt",
          "reviewRequestId",
          "reviewReason",
          "protectedMigrationApproved"
        ],
        "properties": {
          "reviewId": {
            "type": "string",
            "format": "uuid"
          },
          "version": {
            "type": "integer",
            "minimum": 1
          },
          "status": {
            "type": "string",
            "enum": [
              "active",
              "superseded",
              "pending_review",
              "rejected"
            ]
          },
          "driftClass": {
            "type": "string",
            "enum": [
              "initial",
              "additive",
              "protected"
            ]
          },
          "changedFields": {
            "$ref": "#/components/schemas/IdentityReview/properties/changedFields"
          },
          "observedIdentity": {
            "$ref": "#/components/schemas/IdentityObserved"
          },
          "observedAt": {
            "type": "string",
            "format": "date-time"
          },
          "reviewedAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "reviewRequestId": {
            "type": "string",
            "maxLength": 128,
            "nullable": true
          },
          "reviewReason": {
            "type": "string",
            "maxLength": 500,
            "nullable": true
          },
          "protectedMigrationApproved": {
            "type": "boolean"
          }
        }
      },
      "IdentityVersionHistory": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "gatewaySubBusinessId",
          "versions"
        ],
        "properties": {
          "gatewaySubBusinessId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255
          },
          "versions": {
            "type": "array",
            "maxItems": 10000,
            "items": {
              "$ref": "#/components/schemas/IdentityVersion"
            }
          }
        }
      },
      "StoredInvoiceParty": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "email",
          "phoneNumber",
          "tin",
          "country",
          "address",
          "postcode"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "email": {
            "type": "string",
            "format": "email"
          },
          "phoneNumber": {
            "type": "string"
          },
          "tin": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "nullable": true
          },
          "city": {
            "type": "string",
            "nullable": true
          },
          "address": {
            "type": "string"
          },
          "postcode": {
            "type": "string"
          }
        }
      },
      "StoredInvoiceCustomer": {
        "type": "object",
        "additionalProperties": false,
        "description": "Public customer snapshot. Internal parent-business identifiers are intentionally excluded.",
        "required": [
          "id",
          "modules",
          "firstName",
          "lastName",
          "email",
          "phone",
          "tin",
          "country",
          "address",
          "postcode",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "reference": {
            "type": "string",
            "nullable": true
          },
          "modules": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "firstName": {
            "type": "string"
          },
          "lastName": {
            "type": "string"
          },
          "email": {
            "type": "string"
          },
          "phone": {
            "type": "string"
          },
          "tin": {
            "type": "string"
          },
          "country": {
            "type": "string"
          },
          "state": {
            "type": "string",
            "nullable": true
          },
          "city": {
            "type": "string",
            "nullable": true
          },
          "address": {
            "type": "string"
          },
          "postcode": {
            "type": "string"
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "StoredInvoiceTax": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name",
          "rate",
          "amount"
        ],
        "properties": {
          "name": {
            "type": "string"
          },
          "rate": {
            "type": "number",
            "description": "Tax rate in percentage points."
          },
          "amount": {
            "type": "number"
          }
        }
      },
      "StoredInvoiceLineAdjustment": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "id",
          "kind",
          "valueType",
          "value",
          "amount"
        ],
        "properties": {
          "id": {
            "type": "string",
            "description": "Stable adjustment identifier. Generated STORED adjustments use UUIDs; regulator-derived inbound adjustments may use provider identifiers."
          },
          "kind": {
            "type": "string",
            "enum": [
              "allowance",
              "charge"
            ]
          },
          "valueType": {
            "type": "string",
            "enum": [
              "fixed",
              "percentage"
            ]
          },
          "value": {
            "type": "number"
          },
          "amount": {
            "type": "number"
          },
          "description": {
            "type": "string",
            "nullable": true
          }
        }
      },
      "StoredInvoiceLineItem": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "lineNumber",
          "description",
          "quantity",
          "unitPrice",
          "unit",
          "itemAmount",
          "taxes",
          "taxAmount",
          "lineTotalExcludingTax",
          "lineTotalIncludingTax"
        ],
        "properties": {
          "lineNumber": {
            "type": "integer",
            "minimum": 1
          },
          "description": {
            "type": "string"
          },
          "quantity": {
            "type": "number"
          },
          "unitPrice": {
            "type": "number"
          },
          "unit": {
            "type": "string"
          },
          "itemAmount": {
            "type": "number"
          },
          "productCategory": {
            "type": "string",
            "nullable": true
          },
          "hsnCode": {
            "type": "string",
            "nullable": true
          },
          "serviceCategory": {
            "type": "string",
            "nullable": true
          },
          "isicCode": {
            "type": "string",
            "nullable": true
          },
          "allowances": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StoredInvoiceLineAdjustment"
            }
          },
          "charges": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StoredInvoiceLineAdjustment"
            }
          },
          "allowanceTotal": {
            "type": "number"
          },
          "chargeTotal": {
            "type": "number"
          },
          "netAfterAllowance": {
            "type": "number"
          },
          "taxes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StoredInvoiceTax"
            }
          },
          "taxAmount": {
            "type": "number"
          },
          "lineTotalExcludingTax": {
            "type": "number"
          },
          "lineTotalIncludingTax": {
            "type": "number"
          }
        }
      },
      "StoredInvoiceDiscount": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "type",
          "value",
          "amount"
        ],
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "percentage",
              "flat"
            ]
          },
          "value": {
            "type": "number"
          },
          "amount": {
            "type": "number"
          }
        }
      },
      "StoredPaymentDetails": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "type": {
            "type": "string",
            "enum": [
              "local",
              "international"
            ]
          },
          "accountName": {
            "type": "string"
          },
          "accountNumber": {
            "type": "string"
          },
          "bankName": {
            "type": "string"
          },
          "swiftCode": {
            "type": "string"
          },
          "bankAddress": {
            "type": "string"
          },
          "routingNumber": {
            "type": "string"
          },
          "intermediaryBankName": {
            "type": "string"
          },
          "intermediaryBankAddress": {
            "type": "string"
          },
          "correspondentSwiftCode": {
            "type": "string"
          },
          "correspondentBankName": {
            "type": "string"
          },
          "additionalInformation": {
            "type": "string"
          }
        }
      },
      "StoredInvoice": {
        "type": "object",
        "additionalProperties": false,
        "description": "Public STORED invoice projection. gatewaySubBusinessId is the stable represented-business identifier. Internal parent business IDs, child database UUIDs, domain configuration IDs, profile IDs, and mode snapshots are not part of this contract.",
        "required": [
          "id",
          "gatewaySubBusinessId",
          "businessState",
          "invoiceType",
          "issueDate",
          "documentCurrency",
          "taxCurrency",
          "paymentStatus",
          "supplierData",
          "invoiceLineItems",
          "subtotalAmount",
          "taxTotal",
          "allowanceTotal",
          "chargeTotal",
          "totalAmount",
          "amountDue",
          "status",
          "firsStatus",
          "direction",
          "transmissionStatus",
          "createdAt",
          "updatedAt"
        ],
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "gatewaySubBusinessId": {
            "type": "string",
            "minLength": 1,
            "maxLength": 255,
            "description": "Immutable public represented-business identity returned by onboarding and supplied in x-sub-business-id."
          },
          "businessState": {
            "type": "string",
            "enum": [
              "test",
              "live"
            ]
          },
          "invoiceNumber": {
            "type": "string",
            "nullable": true
          },
          "systemInvoiceNumber": {
            "type": "string",
            "nullable": true
          },
          "invoiceReferenceNumber": {
            "type": "string",
            "nullable": true
          },
          "invoiceType": {
            "type": "string",
            "enum": [
              "380",
              "381",
              "384",
              "385",
              "388",
              "389"
            ]
          },
          "billingReferences": {
            "type": "array",
            "nullable": true,
            "items": {
              "$ref": "#/components/schemas/StoredBillingReference"
            }
          },
          "issueDate": {
            "type": "string",
            "format": "date"
          },
          "taxPointDate": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "documentCurrency": {
            "type": "string",
            "enum": [
              "NGN",
              "USD",
              "EUR",
              "GBP",
              "ZAR",
              "KES"
            ]
          },
          "taxCurrency": {
            "type": "string",
            "enum": [
              "NGN",
              "USD",
              "EUR",
              "GBP",
              "ZAR",
              "KES"
            ]
          },
          "paymentStatus": {
            "type": "string",
            "enum": [
              "pending",
              "paid",
              "partially_paid",
              "overdue"
            ]
          },
          "paymentDate": {
            "type": "string",
            "format": "date",
            "nullable": true
          },
          "customer": {
            "$ref": "#/components/schemas/StoredInvoiceCustomer"
          },
          "customerId": {
            "type": "string",
            "format": "uuid",
            "nullable": true
          },
          "supplierData": {
            "$ref": "#/components/schemas/StoredInvoiceParty"
          },
          "payeeData": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/StoredInvoiceParty"
              },
              {
                "type": "object",
                "nullable": true,
                "enum": [
                  null
                ]
              }
            ]
          },
          "taxRepresentativeData": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/StoredInvoiceParty"
              },
              {
                "type": "object",
                "nullable": true,
                "enum": [
                  null
                ]
              }
            ]
          },
          "invoiceLineItems": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/StoredInvoiceLineItem"
            }
          },
          "discountData": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/StoredInvoiceDiscount"
              },
              {
                "type": "object",
                "nullable": true,
                "enum": [
                  null
                ]
              }
            ]
          },
          "subtotalAmount": {
            "type": "number"
          },
          "taxTotal": {
            "type": "number"
          },
          "allowanceTotal": {
            "type": "number"
          },
          "chargeTotal": {
            "type": "number"
          },
          "totalAmount": {
            "type": "number"
          },
          "amountDue": {
            "type": "number"
          },
          "status": {
            "type": "string",
            "enum": [
              "draft",
              "created",
              "validated",
              "submitted",
              "signed",
              "approved",
              "rejected",
              "cancelled",
              "pending_feedback",
              "accepted",
              "disputed",
              "sent",
              "paid"
            ]
          },
          "firsStatus": {
            "type": "string",
            "nullable": true,
            "enum": [
              "submitted",
              "signed",
              "approved",
              "rejected",
              "pending",
              "validated"
            ]
          },
          "firsRejectionReason": {
            "type": "string",
            "nullable": true
          },
          "qrCodeData": {
            "type": "string",
            "nullable": true,
            "description": "Base64 data URL of the generated invoice QR code when available."
          },
          "qrCodeImageUrl": {
            "type": "string",
            "format": "uri",
            "nullable": true
          },
          "direction": {
            "type": "string",
            "enum": [
              "outbound",
              "inbound"
            ]
          },
          "incomingAction": {
            "type": "string",
            "nullable": true,
            "enum": [
              "pending",
              "acknowledged",
              "rejected"
            ]
          },
          "incomingActionAt": {
            "type": "string",
            "format": "date-time",
            "nullable": true
          },
          "incomingRejectionReason": {
            "type": "string",
            "nullable": true
          },
          "transmissionStatus": {
            "type": "string",
            "enum": [
              "not_sent",
              "transmitted",
              "rejected"
            ]
          },
          "notes": {
            "type": "string",
            "nullable": true
          },
          "paymentTerms": {
            "type": "string",
            "nullable": true
          },
          "paymentDetails": {
            "oneOf": [
              {
                "$ref": "#/components/schemas/StoredPaymentDetails"
              },
              {
                "type": "object",
                "nullable": true,
                "enum": [
                  null
                ]
              }
            ]
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "StoredInvoiceEnvelope": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "data",
          "statusCode",
          "message"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/StoredInvoice"
          },
          "statusCode": {
            "type": "integer",
            "enum": [
              200
            ]
          },
          "message": {
            "type": "string"
          }
        }
      },
      "StoredSignAcceptance": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "accepted",
          "invoiceId"
        ],
        "properties": {
          "accepted": {
            "type": "boolean",
            "enum": [
              true
            ]
          },
          "invoiceId": {
            "type": "string",
            "format": "uuid",
            "description": "Persist this ID and use it with GET /invoices/{invoiceId}; acceptance does not mean NRS validation or signing completed."
          }
        }
      },
      "StoredSignAcceptanceEnvelope": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "data",
          "statusCode",
          "message"
        ],
        "properties": {
          "data": {
            "$ref": "#/components/schemas/StoredSignAcceptance"
          },
          "statusCode": {
            "type": "integer",
            "enum": [
              202
            ]
          },
          "message": {
            "type": "string",
            "example": "Invoice accepted for asynchronous signing"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "StoredInvoicePagination": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "total",
          "page",
          "limit",
          "count",
          "previousPage",
          "nextPage",
          "pageCount",
          "totalRecords"
        ],
        "properties": {
          "total": {
            "type": "integer",
            "minimum": 0
          },
          "page": {
            "type": "integer",
            "minimum": 1
          },
          "limit": {
            "type": "integer",
            "minimum": 1,
            "maximum": 100
          },
          "count": {
            "type": "integer",
            "minimum": 0
          },
          "previousPage": {
            "oneOf": [
              {
                "type": "boolean"
              },
              {
                "type": "integer",
                "minimum": 1
              }
            ]
          },
          "nextPage": {
            "oneOf": [
              {
                "type": "boolean"
              },
              {
                "type": "integer",
                "minimum": 1
              }
            ]
          },
          "pageCount": {
            "type": "integer",
            "minimum": 0
          },
          "totalRecords": {
            "type": "integer",
            "minimum": 0
          }
        }
      },
      "StoredInvoiceListEnvelope": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "data",
          "statusCode",
          "message"
        ],
        "properties": {
          "data": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "items",
              "meta"
            ],
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/StoredInvoice"
                }
              },
              "meta": {
                "$ref": "#/components/schemas/StoredInvoicePagination"
              }
            }
          },
          "statusCode": {
            "type": "integer",
            "enum": [
              200
            ]
          },
          "message": {
            "type": "string"
          }
        }
      },
      "SpendSuccessEnvelope": {
        "type": "object",
        "additionalProperties": true,
        "required": [
          "data",
          "statusCode",
          "message"
        ],
        "properties": {
          "data": {
            "nullable": true
          },
          "statusCode": {
            "type": "integer",
            "minimum": 200,
            "maximum": 299
          },
          "message": {
            "type": "string"
          }
        }
      },
      "HealthStatus": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ok"
            ]
          }
        }
      },
      "ReadinessStatus": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "status",
          "checks"
        ],
        "properties": {
          "status": {
            "type": "string",
            "enum": [
              "ready",
              "not_ready"
            ]
          },
          "checks": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "initialized",
              "redis"
            ],
            "properties": {
              "initialized": {
                "type": "boolean"
              },
              "redis": {
                "type": "boolean",
                "description": "Diagnostic only. Shared Redis degradation does not evict every Gateway replica from readiness."
              }
            }
          }
        }
      },
      "InvoiceCustomerInput": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "firstName",
          "lastName",
          "email",
          "phone",
          "country",
          "address",
          "postcode"
        ],
        "properties": {
          "firstName": {
            "type": "string",
            "maxLength": 200
          },
          "lastName": {
            "type": "string",
            "maxLength": 200
          },
          "email": {
            "type": "string",
            "maxLength": 225,
            "format": "email"
          },
          "phone": {
            "type": "string",
            "maxLength": 225,
            "pattern": "^[0-9+]+$"
          },
          "tin": {
            "type": "string",
            "maxLength": 50,
            "pattern": "^[A-Za-z0-9-]+$"
          },
          "country": {
            "type": "string",
            "maxLength": 2,
            "minLength": 2,
            "pattern": "^[A-Za-z]{2}$"
          },
          "state": {
            "type": "string",
            "maxLength": 100
          },
          "city": {
            "type": "string",
            "maxLength": 100
          },
          "address": {
            "type": "string",
            "maxLength": 50,
            "minLength": 3
          },
          "postcode": {
            "type": "string",
            "maxLength": 10
          },
          "module": {
            "type": "string",
            "enum": [
              "invoice"
            ],
            "default": "invoice"
          }
        }
      },
      "InvoiceCustomer": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "format": "uuid"
          },
          "firstName": {
            "type": "string",
            "maxLength": 200
          },
          "lastName": {
            "type": "string",
            "maxLength": 200
          },
          "email": {
            "type": "string",
            "maxLength": 225,
            "format": "email"
          },
          "phone": {
            "type": "string",
            "maxLength": 225,
            "pattern": "^[0-9+]+$"
          },
          "tin": {
            "type": "string",
            "maxLength": 50,
            "pattern": "^[A-Za-z0-9-]+$"
          },
          "country": {
            "type": "string",
            "maxLength": 2,
            "minLength": 2,
            "pattern": "^[A-Za-z]{2}$"
          },
          "state": {
            "type": "string",
            "maxLength": 100
          },
          "city": {
            "type": "string",
            "maxLength": 100
          },
          "address": {
            "type": "string",
            "maxLength": 50,
            "minLength": 3
          },
          "postcode": {
            "type": "string",
            "maxLength": 10
          },
          "module": {
            "type": "string",
            "enum": [
              "invoice"
            ],
            "default": "invoice"
          },
          "reference": {
            "type": "string"
          },
          "modules": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "createdAt": {
            "type": "string",
            "format": "date-time"
          },
          "updatedAt": {
            "type": "string",
            "format": "date-time"
          }
        }
      },
      "InvoiceCustomerEnvelope": {
        "type": "object",
        "properties": {
          "data": {
            "$ref": "#/components/schemas/InvoiceCustomer"
          },
          "statusCode": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      },
      "InvoiceCustomerListEnvelope": {
        "type": "object",
        "properties": {
          "data": {
            "type": "object",
            "properties": {
              "data": {
                "type": "array",
                "items": {
                  "$ref": "#/components/schemas/InvoiceCustomer"
                }
              },
              "meta": {
                "$ref": "#/components/schemas/StoredInvoicePagination"
              }
            }
          },
          "statusCode": {
            "type": "integer"
          },
          "message": {
            "type": "string"
          }
        }
      }
    },
    "headers": {
      "RequestId": {
        "description": "Gateway-generated request correlation ID. Retain this value for support.",
        "schema": {
          "type": "string",
          "format": "uuid"
        }
      },
      "RetryAfter": {
        "description": "Seconds to wait before a permitted retry.",
        "schema": {
          "type": "integer",
          "minimum": 0,
          "maximum": 86400
        }
      },
      "CacheControl": {
        "description": "Gateway responses are marked no-store, including all Problem Details and authenticated management results.",
        "schema": {
          "type": "string",
          "enum": [
            "no-store"
          ]
        }
      },
      "Allow": {
        "description": "Methods accepted for the canonical path.",
        "schema": {
          "type": "string"
        }
      },
      "WwwAuthenticate": {
        "description": "API-key authentication challenge on applicable 401 responses.",
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "GatewayProblem": {
        "description": "Gateway-generated RFC 9457 Problem Details. Branch on code and retry.strategy, not English text. A draining domain rejects new mutations with 409 GW_DOMAIN_DRAINING; authenticated reads and existing STORED transmission completion remain available. A stopping Gateway instance rejects newly arriving non-probe requests with 503 GW_APPLICATION_DRAINING and Retry-After. Preserve mutation identity and follow retry.strategy.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          },
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          },
          "Retry-After": {
            "$ref": "#/components/headers/RetryAfter"
          },
          "Allow": {
            "$ref": "#/components/headers/Allow"
          },
          "WWW-Authenticate": {
            "$ref": "#/components/headers/WwwAuthenticate"
          }
        },
        "content": {
          "application/problem+json": {
            "schema": {
              "$ref": "#/components/schemas/ProblemDetails"
            }
          }
        }
      },
      "NrsOpaqueSuccess": {
        "description": "Sanitized NRS-owned success. Status and body remain regulator-owned; additive response fields are preserved.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          },
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/NrsOpaqueResponse"
            }
          },
          "application/octet-stream": {
            "schema": {
              "type": "string",
              "format": "binary"
            }
          }
        }
      },
      "StoredSignAccepted": {
        "description": "STORED invoice accepted for asynchronous processing. Acceptance is not proof of NRS validation, sign, or transmit completion.",
        "headers": {
          "X-Request-ID": {
            "$ref": "#/components/headers/RequestId"
          },
          "Cache-Control": {
            "$ref": "#/components/headers/CacheControl"
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/StoredSignAcceptanceEnvelope"
            }
          }
        }
      }
    }
  },
  "security": [
    {
      "apiKey": []
    }
  ],
  "paths": {
    "/sub-businesses": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        }
      ],
      "get": {
        "operationId": "listRepresentedBusinesses",
        "summary": "List Represented Businesses",
        "tags": [
          "Represented Businesses"
        ],
        "x-region": [
          "NG"
        ],
        "description": "List active represented-business mappings for the authenticated parent, approved domain, current state, and mode version. Reads use persisted identity snapshots and do not call NRS. gatewaySubBusinessId is the immutable Gateway identity. firsBusinessId and nrsIdentity.nrsBusinessId are the current versioned external mapping and are equal to each other; they may differ from gatewaySubBusinessId only after an audited migration.",
        "parameters": [
          {
            "$ref": "#/components/parameters/Page"
          },
          {
            "$ref": "#/components/parameters/Limit"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of active represented-business mappings and their safe persisted identity snapshots.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RepresentedBusinessList"
                },
                "example": {
                  "items": [
                    {
                      "gatewaySubBusinessId": "nrs-business-demo",
                      "onboardingIntentId": "33333333-3333-4333-8333-333333333333",
                      "domain": "acme",
                      "businessState": "test",
                      "modeVersion": 1,
                      "status": "active",
                      "profile": {
                        "name": "Acme Retail",
                        "legalName": "Acme Retail Limited",
                        "email": "finance@acmeretail.example",
                        "phoneNumber": "+2348000000000",
                        "invoiceNumberPrefix": "ACME"
                      },
                      "firsBusinessId": "nrs-business-demo",
                      "nrsIdentity": {
                        "entityId": "entity-demo",
                        "entityReference": "entity-reference-demo",
                        "nrsBusinessId": "nrs-business-demo",
                        "businessName": "Acme Retail Limited",
                        "tin": "12345678-0001",
                        "irnTemplate": "{{invoice_id}}-2A3A045D-{{YYYYMMDD}}"
                      },
                      "crypto": {
                        "configured": false,
                        "version": 0,
                        "updatedAt": null
                      },
                      "createdAt": "2026-09-15T12:34:56.789Z",
                      "updatedAt": "2026-09-15T12:34:56.789Z"
                    }
                  ],
                  "pagination": {
                    "page": 1,
                    "limit": 50,
                    "total": 1,
                    "totalPages": 1
                  }
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "400": {
            "description": "Invalid, unknown, or repeated pagination query field",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        }
      },
      "post": {
        "operationId": "onboardRepresentedBusiness",
        "summary": "Onboard Represented Business",
        "tags": [
          "Represented Businesses"
        ],
        "x-region": [
          "NG"
        ],
        "description": "Onboard one represented business. A new or pending intent requires transient nrsCredentials; a completed replay with the same idempotency key and normalized profile may omit credentials. New completion and completed replay both return 201, distinguished by replayed. The immutable gatewaySubBusinessId is initially allocated from the verified NRS business ID and never silently remapped; the current external mapping is returned in firsBusinessId and nrsIdentity.nrsBusinessId.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "properties": {
                  "name": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 50,
                    "description": "Optional local display name. It is not used to select or replace the NRS-verified name.",
                    "example": "Acme Retail"
                  },
                  "legalName": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 50,
                    "description": "Optional local legal-name metadata. It is not used to select or replace NRS identity.",
                    "example": "Acme Retail Limited"
                  },
                  "tin": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255,
                    "description": "Optional NRS business selector. If omitted, the NRS entity must have exactly one active business. If supplied, its trimmed, case-insensitive value must match exactly one active NRS business.",
                    "example": "12345678-0001"
                  },
                  "email": {
                    "type": "string",
                    "format": "email",
                    "maxLength": 254,
                    "description": "Optional local contact email for the represented business.",
                    "example": "finance@acmeretail.example"
                  },
                  "phoneNumber": {
                    "type": "string",
                    "maxLength": 20,
                    "pattern": "^\\+[1-9]\\d{6,18}$",
                    "description": "Optional local contact number in E.164 format.",
                    "example": "+2348000000000"
                  },
                  "invoiceNumberPrefix": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 32,
                    "description": "Optional local invoice-number prefix.",
                    "example": "ACME"
                  },
                  "nrsCredentials": {
                    "type": "object",
                    "additionalProperties": false,
                    "required": [
                      "email",
                      "password"
                    ],
                    "description": "Transient NRS portal credentials. Required to start or resume onboarding while the intent is pending; may be omitted only when replaying an already-completed intent. Gateway never forwards them to Spend.",
                    "properties": {
                      "email": {
                        "type": "string",
                        "format": "email",
                        "maxLength": 254,
                        "example": "nrs-owner@acme.example"
                      },
                      "password": {
                        "type": "string",
                        "format": "password",
                        "minLength": 1,
                        "maxLength": 1024,
                        "description": "A non-blank password used only for this NRS verification request.",
                        "example": "replace-at-runtime"
                      }
                    }
                  },
                  "nrsCryptoKeys": {
                    "$ref": "#/components/schemas/NrsCryptoKeys"
                  }
                }
              },
              "examples": {
                "singleActiveBusiness": {
                  "summary": "Onboard the only active NRS business without QR material",
                  "value": {
                    "nrsCredentials": {
                      "email": "nrs-owner@acme.example",
                      "password": "replace-at-runtime"
                    }
                  }
                },
                "selectByTin": {
                  "summary": "Select one of multiple active NRS businesses",
                  "value": {
                    "tin": "12345678-0001",
                    "nrsCredentials": {
                      "email": "nrs-owner@acme.example",
                      "password": "replace-at-runtime"
                    }
                  }
                },
                "withOptionalQrMaterial": {
                  "summary": "Onboard and store optional QR material",
                  "value": {
                    "tin": "12345678-0001",
                    "nrsCredentials": {
                      "email": "nrs-owner@acme.example",
                      "password": "replace-at-runtime"
                    },
                    "nrsCryptoKeys": {
                      "certificate": "nrs-issued-certificate-value",
                      "publicKey": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n"
                    }
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Represented business onboarded or a completed onboarding replayed. gatewaySubBusinessId is the immutable Gateway identity; firsBusinessId equals nrsIdentity.nrsBusinessId for the current NRS mapping.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "onboardingIntentId",
                    "gatewaySubBusinessId",
                    "firsBusinessId",
                    "nrsIdentity",
                    "status",
                    "replayed",
                    "cryptoVersion"
                  ],
                  "properties": {
                    "onboardingIntentId": {
                      "type": "string",
                      "format": "uuid",
                      "description": "Identifier for this onboarding intent."
                    },
                    "gatewaySubBusinessId": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 255,
                      "description": "Immutable Gateway represented-business identity. Use it in represented-business paths and x-sub-business-id."
                    },
                    "firsBusinessId": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 255,
                      "description": "Current versioned NRS business ID; equals nrsIdentity.nrsBusinessId and is used as PASSTHROUGH invoice business_id."
                    },
                    "nrsIdentity": {
                      "$ref": "#/components/schemas/NrsIdentity"
                    },
                    "status": {
                      "type": "string",
                      "enum": [
                        "completed"
                      ]
                    },
                    "replayed": {
                      "type": "boolean",
                      "description": "True when the idempotency key matched an earlier completed onboarding and the original identifiers were returned."
                    },
                    "cryptoVersion": {
                      "type": "integer",
                      "minimum": 0,
                      "description": "Version of stored NRS QR material. Zero means no material was supplied; the first stored pair is version 1 and later replacements increment it."
                    }
                  }
                },
                "examples": {
                  "newlyCompleted": {
                    "summary": "Newly completed onboarding",
                    "value": {
                      "onboardingIntentId": "33333333-3333-4333-8333-333333333333",
                      "gatewaySubBusinessId": "nrs-business-demo",
                      "firsBusinessId": "nrs-business-demo",
                      "nrsIdentity": {
                        "entityId": "entity-demo",
                        "entityReference": "entity-reference-demo",
                        "nrsBusinessId": "nrs-business-demo",
                        "businessName": "Acme Retail Limited",
                        "tin": "12345678-0001",
                        "irnTemplate": "{{invoice_id}}-2A3A045D-{{YYYYMMDD}}"
                      },
                      "status": "completed",
                      "replayed": false,
                      "cryptoVersion": 0
                    }
                  },
                  "completedReplay": {
                    "summary": "Original result returned for a completed replay",
                    "value": {
                      "onboardingIntentId": "33333333-3333-4333-8333-333333333333",
                      "gatewaySubBusinessId": "nrs-business-demo",
                      "firsBusinessId": "nrs-business-demo",
                      "nrsIdentity": {
                        "entityId": "entity-demo",
                        "entityReference": "entity-reference-demo",
                        "nrsBusinessId": "nrs-business-demo",
                        "businessName": "Acme Retail Limited",
                        "tin": "12345678-0001",
                        "irnTemplate": "{{invoice_id}}-2A3A045D-{{YYYYMMDD}}"
                      },
                      "status": "completed",
                      "replayed": true,
                      "cryptoVersion": 0
                    }
                  }
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "400": {
            "description": "Invalid or server-owned onboarding field",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://docs.tryduplo.com/invoicing/nrs/errors/GW_REQUEST_SERVER_FIELD_SUPPLIED",
                  "title": "Server-managed field was supplied",
                  "status": 400,
                  "detail": "The request contains a field that is resolved by the gateway.",
                  "instance": "urn:duplo:request:01991d1c-814d-7a62-8c25-9e0a48bf7322",
                  "code": "GW_REQUEST_SERVER_FIELD_SUPPLIED",
                  "requestId": "01991d1c-814d-7a62-8c25-9e0a48bf7322",
                  "timestamp": "2026-09-15T12:34:56.789Z",
                  "action": {
                    "code": "REMOVE_SERVER_FIELD",
                    "description": "Remove the server-managed field and submit the request again.",
                    "documentation": "https://docs.tryduplo.com/invoicing/nrs/errors/GW_REQUEST_SERVER_FIELD_SUPPLIED"
                  },
                  "retry": {
                    "strategy": "AFTER_CORRECTION"
                  },
                  "message": "The request contains a field that is resolved by the gateway.",
                  "statusCode": 400,
                  "path": "/sub-businesses"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "401": {
            "description": "Missing, invalid, expired, or revoked Gateway API key",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://docs.tryduplo.com/invoicing/nrs/errors/GW_AUTH_API_KEY_REQUIRED",
                  "title": "API key is required",
                  "status": 401,
                  "detail": "The API key header is missing.",
                  "instance": "urn:duplo:request:01991d1c-814d-7a62-8c25-9e0a48bf7322",
                  "code": "GW_AUTH_API_KEY_REQUIRED",
                  "requestId": "01991d1c-814d-7a62-8c25-9e0a48bf7322",
                  "timestamp": "2026-09-15T12:34:56.789Z",
                  "action": {
                    "code": "SUPPLY_API_KEY",
                    "description": "Add the API key header and submit the request again.",
                    "documentation": "https://docs.tryduplo.com/invoicing/nrs/errors/GW_AUTH_API_KEY_REQUIRED"
                  },
                  "retry": {
                    "strategy": "AFTER_CORRECTION"
                  },
                  "message": "The API key header is missing.",
                  "statusCode": 401,
                  "path": "/sub-businesses"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WwwAuthenticate"
              }
            }
          },
          "403": {
            "description": "The API key does not own the host-resolved business, or Duplo is not linked as the taxpayer's NRS application",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "404": {
            "description": "The domain or NRS entity was not found, or a supplied TIN did not match an NRS business",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "409": {
            "description": "Idempotency/profile conflict, ambiguous active NRS-business selection, or approved-state drift",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "413": {
            "description": "The buffered JSON request exceeds the Gateway limit",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "422": {
            "description": "The NRS entity/business is inactive, no active business exists, or the selected business has no IRN template",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "429": {
            "description": "The Gateway management rate limit was exceeded",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "502": {
            "description": "NRS or a required downstream request failed or returned an invalid response",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "503": {
            "description": "The domain registry, tenant authorization, NRS verification configuration, or onboarding service is unavailable; Gateway fails closed",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        }
      }
    },
    "/sub-businesses/{gatewaySubBusinessId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        },
        {
          "$ref": "#/components/parameters/GatewaySubBusinessId"
        }
      ],
      "get": {
        "operationId": "getRepresentedBusiness",
        "summary": "Get Represented Business Information",
        "tags": [
          "Represented Businesses"
        ],
        "x-region": [
          "NG"
        ],
        "description": "Read one represented-business mapping and its current persisted identity version. The operation does not call NRS. The immutable Gateway ID remains stable across reviewed NRS mapping changes; historical aliases stay accepted without exposing another tenant's existence.",
        "responses": {
          "200": {
            "description": "Active represented-business mapping and its persisted onboarding-time NRS identity snapshot.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/RepresentedBusinessInfo"
                },
                "example": {
                  "gatewaySubBusinessId": "nrs-business-demo",
                  "onboardingIntentId": "33333333-3333-4333-8333-333333333333",
                  "domain": "acme",
                  "businessState": "test",
                  "modeVersion": 1,
                  "status": "active",
                  "profile": {
                    "name": "Acme Retail",
                    "legalName": "Acme Retail Limited",
                    "email": "finance@acmeretail.example",
                    "phoneNumber": "+2348000000000",
                    "invoiceNumberPrefix": "ACME"
                  },
                  "firsBusinessId": "nrs-business-demo",
                  "nrsIdentity": {
                    "entityId": "entity-demo",
                    "entityReference": "entity-reference-demo",
                    "nrsBusinessId": "nrs-business-demo",
                    "businessName": "Acme Retail Limited",
                    "tin": "12345678-0001",
                    "irnTemplate": "{{invoice_id}}-2A3A045D-{{YYYYMMDD}}"
                  },
                  "crypto": {
                    "configured": false,
                    "version": 0,
                    "updatedAt": null
                  },
                  "createdAt": "2026-09-15T12:34:56.789Z",
                  "updatedAt": "2026-09-15T12:34:56.789Z"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "400": {
            "description": "The path identifier is empty, non-canonical, or outside the supported length",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "401": {
            "description": "The API key is missing, invalid, expired, or revoked",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WwwAuthenticate"
              }
            }
          },
          "403": {
            "description": "The API key does not own the business resolved from the approved host",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "404": {
            "description": "The represented business is unknown, foreign, inactive, or outside the approved domain's current state and mode version",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://docs.tryduplo.com/invoicing/nrs/errors/GW_SUB_BUSINESS_NOT_FOUND",
                  "title": "Sub-business was not found",
                  "status": 404,
                  "detail": "No approved sub-business is available for that identifier.",
                  "instance": "urn:duplo:request:01991d1c-814d-7a62-8c25-9e0a48bf7322",
                  "code": "GW_SUB_BUSINESS_NOT_FOUND",
                  "requestId": "01991d1c-814d-7a62-8c25-9e0a48bf7322",
                  "timestamp": "2026-09-15T12:34:56.789Z",
                  "action": {
                    "code": "VERIFY_SUB_BUSINESS",
                    "description": "Verify or onboard the sub-business before trying again.",
                    "documentation": "https://docs.tryduplo.com/invoicing/nrs/errors/GW_SUB_BUSINESS_NOT_FOUND"
                  },
                  "retry": {
                    "strategy": "AFTER_CORRECTION"
                  },
                  "message": "No approved sub-business is available for that identifier.",
                  "statusCode": 404,
                  "path": "/sub-businesses/nrs-business-demo"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "429": {
            "description": "The Gateway management rate limit was exceeded",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "503": {
            "description": "The domain registry, tenant authorization, or represented-business information service is unavailable",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        }
      }
    },
    "/sub-businesses/{gatewaySubBusinessId}/nrs-crypto-material": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        },
        {
          "$ref": "#/components/parameters/GatewaySubBusinessId"
        }
      ],
      "post": {
        "operationId": "rotateRepresentedBusinessCrypto",
        "summary": "Set or Replace Represented Business NRS QR Material",
        "tags": [
          "Represented Businesses"
        ],
        "x-region": [
          "NG"
        ],
        "description": "Store both optional NRS QR values for one represented business, or replace a pair stored earlier. Gateway freshly authorizes the exact parent, domain state, and child, hashes the opaque strings, and sends a short-lived signed proof plus the values to Spend for storage. It does not call NRS or validate certificate structure, dates, RSA key size, or a certificate/key match.\n\nThe QR generator interprets the stored public key only when QR generation is attempted. Missing or unusable QR material is not an onboarding, validation, signing, or transmission precondition. A foreign or unknown represented-business ID returns the same not-found result and does not reveal another tenant's data.\n\nThe current end-to-end implementation does not guarantee that retrying this rotation with the same idempotency key is deduplicated. If the response is lost, times out, or is otherwise uncertain, do not automatically retry: retain the idempotency key and request ID, and contact Duplo support to confirm the stored version before submitting another rotation.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "nrsCryptoKeys"
                ],
                "properties": {
                  "nrsCryptoKeys": {
                    "$ref": "#/components/schemas/NrsCryptoKeys"
                  }
                }
              },
              "example": {
                "nrsCryptoKeys": {
                  "certificate": "nrs-issued-certificate-value",
                  "publicKey": "-----BEGIN PUBLIC KEY-----\n...\n-----END PUBLIC KEY-----\n"
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "QR material stored. The first pair changes cryptoVersion from 0 to 1; later successful calls may increment it. Do not assume a repeated same-key request was deduplicated.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "gatewaySubBusinessId",
                    "cryptoVersion",
                    "rotatedAt"
                  ],
                  "properties": {
                    "gatewaySubBusinessId": {
                      "type": "string",
                      "minLength": 1,
                      "maxLength": 255,
                      "description": "Immutable Gateway represented-business identity."
                    },
                    "cryptoVersion": {
                      "type": "integer",
                      "minimum": 1,
                      "description": "One for the first stored pair; incremented for each later successful new replacement."
                    },
                    "rotatedAt": {
                      "type": "string",
                      "format": "date-time",
                      "description": "Time at which this QR-material version was stored."
                    }
                  }
                },
                "example": {
                  "gatewaySubBusinessId": "nrs-business-demo",
                  "cryptoVersion": 1,
                  "rotatedAt": "2026-08-31T15:20:36.000Z"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "400": {
            "description": "Validation error",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://docs.tryduplo.com/invoicing/nrs/errors/GW_REQUEST_VALIDATION_FAILED",
                  "title": "Request validation failed",
                  "status": 400,
                  "detail": "One or more request values are invalid.",
                  "instance": "urn:duplo:request:01991d1c-814d-7a62-8c25-9e0a48bf7322",
                  "code": "GW_REQUEST_VALIDATION_FAILED",
                  "requestId": "01991d1c-814d-7a62-8c25-9e0a48bf7322",
                  "timestamp": "2026-09-15T12:34:56.789Z",
                  "action": {
                    "code": "CORRECT_REQUEST",
                    "description": "Correct the listed request values and submit the request again.",
                    "documentation": "https://docs.tryduplo.com/invoicing/nrs/errors/GW_REQUEST_VALIDATION_FAILED"
                  },
                  "retry": {
                    "strategy": "AFTER_CORRECTION"
                  },
                  "errors": [
                    {
                      "location": "body",
                      "pointer": "/nrsCryptoKeys/privateKey",
                      "code": "UNKNOWN_FIELD",
                      "detail": "This field is not supported."
                    }
                  ],
                  "message": "One or more request values are invalid.",
                  "statusCode": 400,
                  "path": "/sub-businesses/nrs-business-demo/nrs-crypto-material"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "401": {
            "description": "The API key is missing, invalid, or expired",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              },
              "WWW-Authenticate": {
                "$ref": "#/components/headers/WwwAuthenticate"
              }
            }
          },
          "403": {
            "description": "The API key does not own the business resolved from the approved host",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "404": {
            "description": "Represented business not found for this account",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                },
                "example": {
                  "type": "https://docs.tryduplo.com/invoicing/nrs/errors/GW_SUB_BUSINESS_NOT_FOUND",
                  "title": "Sub-business was not found",
                  "status": 404,
                  "detail": "No approved sub-business is available for that identifier.",
                  "instance": "urn:duplo:request:01991d1c-814d-7a62-8c25-9e0a48bf7322",
                  "code": "GW_SUB_BUSINESS_NOT_FOUND",
                  "requestId": "01991d1c-814d-7a62-8c25-9e0a48bf7322",
                  "timestamp": "2026-09-15T12:34:56.789Z",
                  "action": {
                    "code": "VERIFY_SUB_BUSINESS",
                    "description": "Verify or onboard the sub-business before trying again.",
                    "documentation": "https://docs.tryduplo.com/invoicing/nrs/errors/GW_SUB_BUSINESS_NOT_FOUND"
                  },
                  "retry": {
                    "strategy": "AFTER_CORRECTION"
                  },
                  "message": "No approved sub-business is available for that identifier.",
                  "statusCode": 404,
                  "path": "/sub-businesses/nrs-business-demo/nrs-crypto-material"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "409": {
            "description": "The approved domain state changed, the idempotency key conflicts, or an older attestation was rejected",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "413": {
            "description": "The buffered JSON request exceeds the Gateway limit",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "429": {
            "description": "The Gateway management rate limit was exceeded",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Retry-After": {
                "$ref": "#/components/headers/RetryAfter"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "502": {
            "description": "A required downstream request failed",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "503": {
            "description": "The domain registry, tenant authorization, or QR-material storage service is unavailable; Gateway fails closed",
            "content": {
              "application/problem+json": {
                "schema": {
                  "$ref": "#/components/schemas/ProblemDetails"
                }
              }
            },
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            }
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        }
      }
    },
    "/sub-businesses/{gatewaySubBusinessId}/identity-reverification": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        },
        {
          "$ref": "#/components/parameters/GatewaySubBusinessId"
        }
      ],
      "post": {
        "operationId": "reverifyRepresentedBusinessIdentity",
        "summary": "Reverify Represented Business Identity",
        "tags": [
          "Represented Businesses"
        ],
        "description": "Authenticate to NRS transiently, compare the current provider identity with the active stored version, and create a review when drift exists. Credentials are not persisted or forwarded to Spend. A protected entity ID, business ID, or TIN change is never applied by this public operation.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "nrsCredentials"
                ],
                "properties": {
                  "nrsCredentials": {
                    "$ref": "#/components/schemas/NrsCredentials"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Identity unchanged or an idempotent result returned.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentityReview"
                }
              }
            }
          },
          "201": {
            "description": "Identity review created.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentityReview"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "409": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "413": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "415": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "422": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/sub-businesses/{gatewaySubBusinessId}/identity-reviews/{reviewId}/decision": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        },
        {
          "$ref": "#/components/parameters/GatewaySubBusinessId"
        },
        {
          "$ref": "#/components/parameters/ReviewId"
        }
      ],
      "post": {
        "operationId": "decideRepresentedBusinessIdentityReview",
        "summary": "Decide a Non-Protected Identity Review",
        "tags": [
          "Represented Businesses"
        ],
        "description": "Apply additive/name/template/activity drift or reject a pending review. The public tenant route cannot approve protected entity-ID, business-ID, or TIN migrations; protectedMigration: true returns GW_IDENTITY_PROTECTED_MIGRATION_REQUIRED and an administrator must use the audited operator boundary.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "action",
                  "reason"
                ],
                "properties": {
                  "action": {
                    "type": "string",
                    "enum": [
                      "apply",
                      "reject"
                    ]
                  },
                  "reason": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 500
                  },
                  "protectedMigration": {
                    "type": "boolean",
                    "default": false,
                    "description": "The public route accepts false/omitted only; true requires the excluded administrator endpoint."
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Review applied or rejected.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentityReview"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "409": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "413": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "415": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/sub-businesses/{gatewaySubBusinessId}/identity-versions": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        },
        {
          "$ref": "#/components/parameters/GatewaySubBusinessId"
        }
      ],
      "get": {
        "operationId": "listRepresentedBusinessIdentityVersions",
        "summary": "List Represented Business Identity Versions",
        "tags": [
          "Represented Businesses"
        ],
        "description": "Return immutable identity observations and review audit metadata for the represented business. This read does not call NRS.",
        "responses": {
          "200": {
            "description": "Identity version history.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/IdentityVersionHistory"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/invoices": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        }
      ],
      "get": {
        "operationId": "listStoredInvoices",
        "summary": "List Stored Invoices",
        "tags": [
          "Stored Invoices"
        ],
        "description": "List STORED-mode invoices scoped to the authenticated parent and approved test/live state. Unknown or repeated query fields are rejected. Authenticated reads remain available while the domain is draining.",
        "parameters": [
          {
            "$ref": "#/components/parameters/InvoicePage"
          },
          {
            "$ref": "#/components/parameters/InvoiceLimit"
          },
          {
            "$ref": "#/components/parameters/FirsStatus"
          }
        ],
        "responses": {
          "200": {
            "description": "One page of parent-scoped STORED invoices.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoredInvoiceListEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/invoices/{invoiceId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        },
        {
          "$ref": "#/components/parameters/InvoiceId"
        }
      ],
      "get": {
        "operationId": "getStoredInvoice",
        "summary": "Get Stored Invoice",
        "tags": [
          "Stored Invoices"
        ],
        "description": "Read one STORED invoice owned by the authenticated parent. Unknown and cross-tenant identifiers produce the same safe not-found response. Authenticated reads remain available while the domain is draining.",
        "responses": {
          "200": {
            "description": "Parent-scoped STORED invoice.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StoredInvoiceEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/invoices/{invoiceId}/transmit": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        },
        {
          "$ref": "#/components/parameters/InvoiceId"
        }
      ],
      "post": {
        "operationId": "transmitStoredInvoice",
        "summary": "Transmit Stored Invoice",
        "tags": [
          "Stored Invoices"
        ],
        "description": "Request transmission of one signed STORED invoice. The represented-business ID is the immutable Gateway ID. Preserve the required idempotency key and identical body for a retry allowed by Problem Details. Completion of an existing STORED invoice remains authorized during domain draining under its pinned business state and mode version. Signed invoices awaiting NRS transmission block mode/state changes and disable. Email delivery and local cancellation do not discharge NRS transmission obligations; canceled invoices cannot be transmitted and require audited support reconciliation.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "required": [
                  "gatewaySubBusinessId"
                ],
                "properties": {
                  "gatewaySubBusinessId": {
                    "type": "string",
                    "minLength": 1,
                    "maxLength": 255
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Transmission command processed.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/SpendSuccessEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "409": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "413": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "415": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "422": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/health": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        }
      ],
      "get": {
        "operationId": "getGatewayHealth",
        "summary": "Get Compatibility Health",
        "tags": [
          "Health"
        ],
        "security": [],
        "description": "Process liveness only. Spend, administrator, NRS, Redis, and processor degradation do not change this response.",
        "responses": {
          "200": {
            "description": "Gateway process is alive.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthStatus"
                }
              }
            }
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/health/live": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        }
      ],
      "get": {
        "operationId": "getGatewayLiveness",
        "summary": "Get Gateway Liveness",
        "tags": [
          "Health"
        ],
        "security": [],
        "description": "Process liveness only. Spend, administrator, NRS, Redis, and processor degradation do not change this response.",
        "responses": {
          "200": {
            "description": "Gateway process is alive.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/HealthStatus"
                }
              }
            }
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/health/ready": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        }
      ],
      "get": {
        "operationId": "getGatewayReadiness",
        "summary": "Get Gateway Readiness",
        "tags": [
          "Health"
        ],
        "security": [],
        "description": "Reports readiness after local initialization and becomes not_ready immediately when process shutdown starts. Returns HTTP 503 during startup or shutdown, with the ReadinessStatus JSON body rather than Problem Details. Shared dependency outages remain diagnostic and do not remove every Gateway replica from service. Compatibility and liveness probes remain available during shutdown.",
        "responses": {
          "200": {
            "description": "Gateway can return deterministic responses.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadinessStatus"
                }
              }
            }
          },
          "503": {
            "description": "Local initialization is incomplete or this Gateway instance is shutting down.",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ReadinessStatus"
                }
              }
            }
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/api/v1/utilities/authenticate": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        }
      ],
      "post": {
        "operationId": "authenticateNrsTaxpayer",
        "summary": "Authenticate NRS Taxpayer",
        "tags": [
          "NRS Diagnostics"
        ],
        "description": "Unbilled direct NRS authentication diagnostic. Taxpayer credentials are forwarded only to NRS. A valid success must contain the v1 authentication envelope; provider-owned credential failures are not blamed on the customer API key.",
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NrsDirectAuthenticationRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "405": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "409": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "413": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "415": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "422": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/api/v1/entity/{entityId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        },
        {
          "$ref": "#/components/parameters/EntityId"
        }
      ],
      "get": {
        "operationId": "getNrsEntity",
        "summary": "Get NRS Entity",
        "tags": [
          "NRS Diagnostics"
        ],
        "description": "Unbilled direct entity lookup. Gateway validates the v1 success envelope before relaying it.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "405": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "409": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "413": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "415": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "422": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/api/v1/invoice/transmit/lookup/tin/{tin}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        },
        {
          "$ref": "#/components/parameters/Tin"
        }
      ],
      "get": {
        "operationId": "lookupNrsRecipientByTin",
        "summary": "Look Up NRS Recipient",
        "tags": [
          "NRS Diagnostics"
        ],
        "description": "Unbilled recipient-capability lookup. No represented-business header is required.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "202": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "204": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "405": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "409": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "413": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "415": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "422": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/api/v1/invoice/transmit/self-health-check": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        }
      ],
      "get": {
        "operationId": "getNrsSenderHealth",
        "summary": "Get NRS Sender Health",
        "tags": [
          "NRS Diagnostics"
        ],
        "description": "Unbilled NRS sender/provider health call. This is not Gateway liveness or readiness.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "202": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "204": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "405": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "409": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "413": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "415": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "422": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/api/v1/invoice/resources/{resource}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        },
        {
          "$ref": "#/components/parameters/NrsResource"
        }
      ],
      "get": {
        "operationId": "getNrsReferenceResource",
        "summary": "Get NRS Reference Resource",
        "tags": [
          "NRS Resources"
        ],
        "description": "Fetch one allowlisted NRS reference collection. Other resource names and every query parameter are rejected by Gateway.",
        "responses": {
          "200": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "202": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "204": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "405": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "409": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "413": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "415": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "422": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/api/v1/invoice/validate": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        }
      ],
      "post": {
        "operationId": "validateNrsInvoice",
        "summary": "Validate NRS Invoice",
        "tags": [
          "NRS Invoice Operations"
        ],
        "description": "PASSTHROUGH-only, unbilled validation. Gateway verifies business_id and supplier TIN against the represented business before calling NRS.",
        "parameters": [
          {
            "$ref": "#/components/parameters/SubBusinessId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/NrsInvoiceDocument"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "202": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "204": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "405": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "409": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "413": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "415": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "422": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/api/v1/invoice/sign": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        }
      ],
      "post": {
        "operationId": "signOrStoreNrsInvoice",
        "summary": "Sign or Store NRS Invoice",
        "tags": [
          "NRS Invoice Operations"
        ],
        "description": "Billable operation whose request and response are selected by the domain's approved invoice-handling mode, not by a caller-supplied discriminator. Both modes require x-sub-business-id. PASSTHROUGH accepts PassthroughInvoiceSignInput, treats x-idempotency-key as optional in the current API version, debits synchronously, and returns the sanitized NRS HTTP 200 response; x-attempt-number and x-invoice-reference apply only to this mode. Unknown PASSTHROUGH post-debit outcomes return GW_SIGN_OUTCOME_UNCONFIRMED with operationId and must not be resubmitted. STORED accepts StoredInvoiceInput, requires x-idempotency-key, and returns HTTP 202 after durable intake; later processor failures are owned by Spend. Sending the body shape for the other approved mode is a validation error. OpenAPI cannot express a header that is required only for one server-selected body branch, so x-idempotency-key is structurally optional here but operationally mandatory in STORED mode. For STORED, create or resolve an invoice customer through the customer operations under Stored Invoices and send its customerId. Intake accepts omission, but the asynchronous NRS readiness check rejects an invoice without a customer; there is no later Gateway endpoint to attach one. PASSTHROUGH uses customer-party details in the NRS document and does not require a Duplo customerId.",
        "parameters": [
          {
            "$ref": "#/components/parameters/SubBusinessId"
          },
          {
            "$ref": "#/components/parameters/OptionalLegacyIdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/AttemptNumber"
          },
          {
            "$ref": "#/components/parameters/InvoiceReference"
          }
        ],
        "requestBody": {
          "required": true,
          "description": "Send exactly the schema selected by the domain's approved mode. There is no mode field in the payload: PASSTHROUGH uses the regulator-owned snake_case document, while STORED uses Duplo's camelCase intake document and omits all server-owned routing fields.",
          "content": {
            "application/json": {
              "schema": {
                "oneOf": [
                  {
                    "$ref": "#/components/schemas/PassthroughInvoiceSignInput"
                  },
                  {
                    "$ref": "#/components/schemas/StoredInvoiceInput"
                  }
                ]
              },
              "examples": {
                "passthrough": {
                  "summary": "PASSTHROUGH NRS document",
                  "value": {
                    "business_id": "5be71d46-045d-4098-a466-4708afe7edac",
                    "irn": "INV000001-2A3A045D-20260818",
                    "issue_date": "2026-08-18",
                    "invoice_type_code": "381",
                    "accounting_supplier_party": {
                      "party_name": "Acme Retail Limited",
                      "tin": "12345678-0001"
                    }
                  }
                },
                "stored": {
                  "summary": "STORED intake document",
                  "value": {
                    "invoiceNumber": "INV-0001",
                    "invoiceReferenceNumber": "INV000001-2A3A045D-20260818",
                    "invoiceType": "381",
                    "issueDate": "2026-08-18",
                    "documentCurrency": "NGN",
                    "taxCurrency": "NGN",
                    "paymentStatus": "pending",
                    "supplierData": {
                      "name": "Acme Retail Limited",
                      "email": "invoice@acme.example",
                      "phoneNumber": "+2348012345678",
                      "tin": "12345678-0001",
                      "country": "NG",
                      "state": "Lagos",
                      "city": "Lagos",
                      "address": "1 Integration Road",
                      "postcode": "100001"
                    },
                    "customerId": "55555555-5555-4555-8555-555555555555",
                    "items": [
                      {
                        "description": "Integration service",
                        "unit": "HUR",
                        "quantity": 1,
                        "unitPrice": 1000,
                        "taxes": [
                          {
                            "name": "STANDARD_VAT",
                            "rate": 7.5
                          }
                        ],
                        "serviceCategory": "Computer programming activities",
                        "isicCode": "6201"
                      }
                    ],
                    "notes": "Payment due in 30 days"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "202": {
            "$ref": "#/components/responses/StoredSignAccepted"
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "405": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "409": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "413": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "415": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "422": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/api/v1/invoice/transmit/lookup/{irn}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        },
        {
          "$ref": "#/components/parameters/Irn"
        }
      ],
      "get": {
        "operationId": "lookupSignedNrsInvoice",
        "summary": "Look Up Signed Invoice",
        "tags": [
          "NRS Invoice Operations"
        ],
        "description": "PASSTHROUGH-only, unbilled lookup. The IRN must have a durable binding to the represented business.",
        "parameters": [
          {
            "$ref": "#/components/parameters/SubBusinessId"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "202": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "204": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "405": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "409": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "413": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "415": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "422": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/api/v1/invoice/transmit/{irn}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        },
        {
          "$ref": "#/components/parameters/Irn"
        }
      ],
      "post": {
        "operationId": "transmitSignedNrsInvoice",
        "summary": "Transmit Signed Invoice",
        "tags": [
          "NRS Invoice Operations"
        ],
        "description": "PASSTHROUGH-only mutation. Gateway creates a durable Spend claim before calling NRS. Only the exact NRS v1 synchronous success envelope completes the claim; timeout, transport loss, 202/204, or malformed success returns GW_TRANSMIT_OUTCOME_UNCONFIRMED with operationId and is never replayed automatically. Send an empty JSON object.",
        "parameters": [
          {
            "$ref": "#/components/parameters/SubBusinessId"
          },
          {
            "$ref": "#/components/parameters/OptionalStandardIdempotencyKey"
          },
          {
            "$ref": "#/components/parameters/OptionalLegacyIdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "type": "object",
                "additionalProperties": false,
                "maxProperties": 0
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/NrsOpaqueSuccess"
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "405": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "409": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "413": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "415": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "422": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      },
      "patch": {
        "operationId": "acknowledgeInboundNrsInvoiceUnavailable",
        "summary": "Acknowledge Inbound Invoice (Unavailable)",
        "tags": [
          "NRS Invoice Operations"
        ],
        "security": [],
        "description": "Recognized for compatibility but disabled in every environment until authoritative IRN ownership is available. Gateway returns 503 GW_INVOICE_OPERATION_UNAVAILABLE before tenant resolution or an NRS call.",
        "responses": {
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/api/v1/invoice/download/{irn}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        },
        {
          "$ref": "#/components/parameters/Irn"
        }
      ],
      "get": {
        "operationId": "downloadInboundNrsInvoiceUnavailable",
        "summary": "Download Inbound Invoice (Unavailable)",
        "tags": [
          "NRS Invoice Operations"
        ],
        "security": [],
        "description": "Recognized for compatibility but disabled in every environment until authoritative IRN ownership is available. Gateway returns 503 GW_INVOICE_OPERATION_UNAVAILABLE before tenant resolution or an NRS call.",
        "responses": {
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "508": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "default": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    },
    "/customers": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        }
      ],
      "post": {
        "operationId": "createInvoiceCustomer",
        "summary": "Create an Invoice Customer",
        "tags": [
          "Stored Invoices"
        ],
        "description": "STORED invoice flow: create or resolve the customer before submitting its customerId through POST /api/v1/invoice/sign. PASSTHROUGH does not require this step. Customer routes themselves are not restricted by invoice-handling mode. Create an invoice customer using your approved Gateway domain and x-api-key. Ownership, test/live state and the invoice module are derived by the service; do not supply business ownership fields. Customers are scoped to the parent business and state and may be reused across represented businesses and approved domains with the same parent/state. No x-sub-business-id is required. Duplicate email/TIN conflicts return 409 GW_CUSTOMER_ALREADY_EXISTS; use GET /customers?email=... to resolve an uncertain creation before retrying. New customer creation returns 409 GW_DOMAIN_DRAINING during a domain transition.",
        "responses": {
          "201": {
            "description": "Create an Invoice Customer",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceCustomerEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "409": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "413": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "415": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvoiceCustomerInput"
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listInvoiceCustomers",
        "summary": "List Invoice Customers",
        "tags": [
          "Stored Invoices"
        ],
        "description": "STORED invoice flow: create or resolve the customer before submitting its customerId through POST /api/v1/invoice/sign. PASSTHROUGH does not require this step. Customer routes themselves are not restricted by invoice-handling mode. List invoice customers in the authenticated parent business and test/live state using bounded page/limit pagination and an optional exact email filter. This customer set is shared across represented businesses and approved domains with the same parent/state. No x-sub-business-id is required. Authenticated reads remain available during domain draining.",
        "responses": {
          "200": {
            "description": "List Invoice Customers",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceCustomerListEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "409": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "413": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "415": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 1000000,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "email",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "email",
              "maxLength": 225
            }
          },
          {
            "name": "module",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "invoice"
              ]
            }
          }
        ]
      }
    },
    "/customers/{customerId}": {
      "parameters": [
        {
          "$ref": "#/components/parameters/CallerRequestId"
        },
        {
          "name": "customerId",
          "in": "path",
          "required": true,
          "schema": {
            "type": "string",
            "format": "uuid",
            "pattern": "^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}$"
          }
        }
      ],
      "get": {
        "operationId": "getInvoiceCustomer",
        "summary": "Get an Invoice Customer",
        "tags": [
          "Stored Invoices"
        ],
        "description": "STORED invoice flow: create or resolve the customer before submitting its customerId through POST /api/v1/invoice/sign. PASSTHROUGH does not require this step. Customer routes themselves are not restricted by invoice-handling mode. Retrieve one invoice customer by UUID in the authenticated parent business and test/live state. Inaccessible and missing IDs return 404 GW_CUSTOMER_NOT_FOUND. No x-sub-business-id is required. Authenticated reads remain available during domain draining.",
        "responses": {
          "200": {
            "description": "Get an Invoice Customer",
            "headers": {
              "X-Request-ID": {
                "$ref": "#/components/headers/RequestId"
              },
              "Cache-Control": {
                "$ref": "#/components/headers/CacheControl"
              }
            },
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceCustomerEnvelope"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "401": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "403": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "404": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "409": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "413": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "415": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "429": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "500": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "502": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "503": {
            "$ref": "#/components/responses/GatewayProblem"
          },
          "504": {
            "$ref": "#/components/responses/GatewayProblem"
          }
        },
        "x-region": [
          "NG"
        ]
      }
    }
  }
}
