{
  "openapi": "3.1.0",
  "info": {
    "title": "NEXTOREx Public API",
    "version": "1.0.0",
    "description": "Server-to-server API for NEXTOREx tenants (plus one keyless public catalog). Authenticate with `Authorization: Bearer <api-key>`. Effective access = key scope ∩ role permissions ∩ purchased app ∩ company ∩ hierarchy. Full guide: /developers."
  },
  "servers": [
    {
      "url": "https://{apiHost}/api/public/v1",
      "variables": {
        "apiHost": {
          "default": "YOUR_API_HOST",
          "description": "The NEXTOREx API host supplied with your Developer API access."
        }
      }
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Catalog"
    },
    {
      "name": "Identity"
    },
    {
      "name": "Hierarchy"
    },
    {
      "name": "CRM"
    },
    {
      "name": "ERP"
    },
    {
      "name": "Education"
    },
    {
      "name": "Billing"
    }
  ],
  "paths": {
    "/billing/invoices": {
      "get": {
        "operationId": "listInvoices",
        "tags": [
          "Billing"
        ],
        "summary": "List invoices",
        "x-required-scope": "billing:read",
        "x-required-permissions": [
          "BillingInvoice.view"
        ],
        "x-sorts": [
          "created_at",
          "updated_at",
          "issue_date",
          "due_date"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "updated_at",
                "issue_date",
                "due_date",
                "-created_at",
                "-updated_at",
                "-issue_date",
                "-due_date"
              ],
              "default": "-created_at"
            },
            "description": "One allow-listed sort. Prefix with - for descending."
          },
          {
            "name": "filter[status]",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter[currency]",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter[number]",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter[issued_from]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "filter[issued_to]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "filter[due_from]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "filter[due_to]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date"
            }
          },
          {
            "name": "filter[created_from]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "filter[updated_from]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "filter[node]",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Public node reference (nd_...) of one descendant node. Unknown or out-of-scope references return 404."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Invoice"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Invalid"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/billing/invoices/{id}": {
      "get": {
        "operationId": "getInvoice",
        "tags": [
          "Billing"
        ],
        "summary": "Get a invoice",
        "x-required-scope": "billing:read",
        "x-required-permissions": [
          "BillingInvoice.view"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Invoice public id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Invoice"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/billing/invoices/{id}/payment-link": {
      "post": {
        "operationId": "createInvoicePaymentLink",
        "tags": [
          "Billing"
        ],
        "summary": "Get a payment link for an invoice",
        "x-required-scope": "billing:write",
        "x-required-permissions": [
          "BillingInvoice.send",
          "BillingInvoice.view"
        ],
        "x-idempotency": "required",
        "description": "Accepts NO body or query input. Returns the hosted checkout URL for the invoice's remaining balance; an unexpired link is reused. 409 invoice_not_payable / payment_not_available. No charge is made.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Public id of the record"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/PaymentLink"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Invalid"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/billing/subscription": {
      "get": {
        "operationId": "getSubscription",
        "tags": [
          "Billing"
        ],
        "summary": "The NEXTOREx subscription",
        "description": "The tenant's own NEXTOREx subscription. A singleton: no id.",
        "x-required-scope": "billing:read",
        "x-required-permissions": [
          "BillingSubscription.view"
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Subscription"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/catalog": {
      "get": {
        "operationId": "getCatalog",
        "tags": [
          "Catalog"
        ],
        "summary": "Commercial catalog (keyless)",
        "description": "The official NEXTOREx SaaS catalog: apps, plans, prices, limits. Public, browser-safe, no key and no Developer API entitlement required. Cached for 5 minutes (ETag / If-None-Match supported).",
        "security": [],
        "x-keyless": true,
        "parameters": [
          {
            "name": "app",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "erp",
                "crm",
                "education"
              ]
            },
            "description": "Return one app only."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Catalog"
                    }
                  }
                }
              }
            }
          },
          "304": {
            "description": "Not modified (If-None-Match matched)."
          },
          "422": {
            "$ref": "#/components/responses/Invalid"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/crm/leads": {
      "get": {
        "operationId": "listLeads",
        "tags": [
          "CRM"
        ],
        "summary": "List leads",
        "x-required-scope": "crm:read",
        "x-required-permissions": [
          "Lead.view"
        ],
        "x-sorts": [
          "created_at",
          "updated_at"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "updated_at",
                "-created_at",
                "-updated_at"
              ],
              "default": "-created_at"
            },
            "description": "One allow-listed sort. Prefix with - for descending."
          },
          {
            "name": "filter[lifecycle]",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "active",
                "converted",
                "invoice_generated",
                "archived"
              ]
            }
          },
          {
            "name": "filter[priority]",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "low",
                "medium",
                "high",
                "urgent"
              ]
            }
          },
          {
            "name": "filter[is_hot]",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "filter[email]",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter[created_from]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "filter[created_to]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "filter[updated_from]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "filter[node]",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Public node reference (nd_...) of one descendant node. Unknown or out-of-scope references return 404."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Lead"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Invalid"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createLead",
        "tags": [
          "CRM"
        ],
        "summary": "Create a lead",
        "x-required-scope": "crm:write",
        "x-required-permissions": [
          "Lead.create",
          "Lead.view"
        ],
        "x-idempotency": "required",
        "description": "409 duplicate_lead when the email or phone already exists inside the key's subtree.",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LeadCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Lead"
                    }
                  }
                }
              }
            },
            "headers": {
              "Location": {
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Invalid"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/crm/leads/{id}": {
      "get": {
        "operationId": "getLead",
        "tags": [
          "CRM"
        ],
        "summary": "Get a lead",
        "x-required-scope": "crm:read",
        "x-required-permissions": [
          "Lead.view"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Lead public id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Lead"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "patch": {
        "operationId": "updateLead",
        "tags": [
          "CRM"
        ],
        "summary": "Update a lead (partial)",
        "x-required-scope": "crm:write",
        "x-required-permissions": [
          "Lead.update",
          "Lead.view"
        ],
        "x-idempotency": "optional",
        "description": "409 lead_locked when the lead is locked by its business flow.",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Public id of the record"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKeyOptional"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/LeadUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Lead"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Invalid"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/education/students": {
      "get": {
        "operationId": "listStudents",
        "tags": [
          "Education"
        ],
        "summary": "List students",
        "x-required-scope": "education:read",
        "x-required-permissions": [
          "Student.view"
        ],
        "x-requires-app": "education",
        "x-sorts": [
          "name",
          "created_at",
          "updated_at"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "name",
                "created_at",
                "updated_at",
                "-name",
                "-created_at",
                "-updated_at"
              ],
              "default": "name"
            },
            "description": "One allow-listed sort. Prefix with - for descending."
          },
          {
            "name": "filter[status]",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter[is_active]",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "filter[code]",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter[email]",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter[created_from]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "filter[created_to]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "filter[updated_from]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "filter[node]",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Public node reference (nd_...) of one descendant node. Unknown or out-of-scope references return 404."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Student"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Invalid"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createStudent",
        "tags": [
          "Education"
        ],
        "summary": "Admit a student",
        "x-required-scope": "education:write",
        "x-required-permissions": [
          "Student.create",
          "Student.view"
        ],
        "x-idempotency": "required",
        "x-requires-app": "education",
        "description": "422 resource_limit_reached when the plan's active-student limit is exhausted (nothing is written).",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StudentCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Student"
                    }
                  }
                }
              }
            },
            "headers": {
              "Location": {
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Invalid"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/education/students/{id}": {
      "get": {
        "operationId": "getStudent",
        "tags": [
          "Education"
        ],
        "summary": "Get a student",
        "x-required-scope": "education:read",
        "x-required-permissions": [
          "Student.view"
        ],
        "x-requires-app": "education",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Student public id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Student"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "patch": {
        "operationId": "updateStudent",
        "tags": [
          "Education"
        ],
        "summary": "Update a student profile (partial)",
        "x-required-scope": "education:write",
        "x-required-permissions": [
          "Student.edit",
          "Student.view"
        ],
        "x-idempotency": "optional",
        "x-requires-app": "education",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Public id of the record"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKeyOptional"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/StudentUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Student"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Invalid"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/erp/customers": {
      "get": {
        "operationId": "listCustomers",
        "tags": [
          "ERP"
        ],
        "summary": "List customers",
        "x-required-scope": "erp:read",
        "x-required-permissions": [
          "Customer.view"
        ],
        "x-sorts": [
          "name",
          "created_at",
          "updated_at"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "name",
                "created_at",
                "updated_at",
                "-name",
                "-created_at",
                "-updated_at"
              ],
              "default": "name"
            },
            "description": "One allow-listed sort. Prefix with - for descending."
          },
          {
            "name": "filter[is_active]",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "filter[email]",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter[phone]",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter[created_from]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "filter[created_to]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "filter[updated_from]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "filter[node]",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Public node reference (nd_...) of one descendant node. Unknown or out-of-scope references return 404."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Customer"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Invalid"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "post": {
        "operationId": "createCustomer",
        "tags": [
          "ERP"
        ],
        "summary": "Create a customer",
        "x-required-scope": "erp:write",
        "x-required-permissions": [
          "Customer.create",
          "Customer.view"
        ],
        "x-idempotency": "required",
        "parameters": [
          {
            "$ref": "#/components/parameters/IdempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerCreate"
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Created",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Customer"
                    }
                  }
                }
              }
            },
            "headers": {
              "Location": {
                "schema": {
                  "type": "string",
                  "format": "uri"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Invalid"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/erp/customers/{id}": {
      "get": {
        "operationId": "getCustomer",
        "tags": [
          "ERP"
        ],
        "summary": "Get a customer",
        "x-required-scope": "erp:read",
        "x-required-permissions": [
          "Customer.view"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Customer public id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Customer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      },
      "patch": {
        "operationId": "updateCustomer",
        "tags": [
          "ERP"
        ],
        "summary": "Update a customer (partial)",
        "x-required-scope": "erp:write",
        "x-required-permissions": [
          "Customer.edit",
          "Customer.view"
        ],
        "x-idempotency": "optional",
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Public id of the record"
          },
          {
            "$ref": "#/components/parameters/IdempotencyKeyOptional"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerUpdate"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Customer"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "409": {
            "$ref": "#/components/responses/Conflict"
          },
          "422": {
            "$ref": "#/components/responses/Invalid"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/erp/products": {
      "get": {
        "operationId": "listProducts",
        "tags": [
          "ERP"
        ],
        "summary": "List products",
        "x-required-scope": "erp:read",
        "x-required-permissions": [
          "Product.view"
        ],
        "x-sorts": [
          "name",
          "created_at",
          "updated_at"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "name",
                "created_at",
                "updated_at",
                "-name",
                "-created_at",
                "-updated_at"
              ],
              "default": "name"
            },
            "description": "One allow-listed sort. Prefix with - for descending."
          },
          {
            "name": "filter[is_active]",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "filter[can_sell]",
            "in": "query",
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "filter[type]",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "standard",
                "bundle"
              ]
            }
          },
          {
            "name": "filter[sku]",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter[barcode]",
            "in": "query",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "filter[created_from]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "filter[created_to]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "filter[updated_from]",
            "in": "query",
            "schema": {
              "type": "string",
              "format": "date-time"
            }
          },
          {
            "name": "filter[node]",
            "in": "query",
            "schema": {
              "type": "string"
            },
            "description": "Public node reference (nd_...) of one descendant node. Unknown or out-of-scope references return 404."
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Product"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Invalid"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/erp/products/{id}": {
      "get": {
        "operationId": "getProduct",
        "tags": [
          "ERP"
        ],
        "summary": "Get a product",
        "x-required-scope": "erp:read",
        "x-required-permissions": [
          "Product.view"
        ],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Product public id"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Product"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/hierarchy/nodes": {
      "get": {
        "operationId": "listHierarchyNodes",
        "tags": [
          "Hierarchy"
        ],
        "summary": "List nodes",
        "description": "The key's own node and its descendants. Needs a valid key, no scope.",
        "x-required-scope": null,
        "x-required-permissions": [],
        "x-sorts": [
          "created_at"
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/Limit"
          },
          {
            "$ref": "#/components/parameters/Cursor"
          },
          {
            "name": "sort",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "created_at",
                "-created_at"
              ],
              "default": "created_at"
            },
            "description": "One allow-listed sort. Prefix with - for descending."
          },
          {
            "name": "filter[level]",
            "in": "query",
            "schema": {
              "type": "string",
              "enum": [
                "company",
                "bg",
                "le",
                "ou",
                "su"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data",
                    "pagination"
                  ],
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Node"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "422": {
            "$ref": "#/components/responses/Invalid"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/hierarchy/nodes/{id}": {
      "get": {
        "operationId": "getHierarchyNode",
        "tags": [
          "Hierarchy"
        ],
        "summary": "Get a node",
        "x-required-scope": null,
        "x-required-permissions": [],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            },
            "description": "Node public id (nd_...)"
          }
        ],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Node"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    },
    "/me": {
      "get": {
        "operationId": "getMe",
        "tags": [
          "Identity"
        ],
        "summary": "Who am I",
        "description": "Metadata of the calling key. Needs a valid key but no scope.",
        "x-required-scope": null,
        "x-required-permissions": [],
        "responses": {
          "200": {
            "description": "OK",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "required": [
                    "data"
                  ],
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Me"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/BadAuth"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key of the form nx_<live|test>_<prefix>_<secret>, created by an authorised user in the NEXTOREx dashboard. Shown once."
      }
    },
    "parameters": {
      "Limit": {
        "name": "limit",
        "in": "query",
        "schema": {
          "type": "integer",
          "minimum": 1,
          "maximum": 100,
          "default": 25
        },
        "description": "Page size. Values above 100 are rejected with 422, never clamped."
      },
      "Cursor": {
        "name": "cursor",
        "in": "query",
        "schema": {
          "type": "string",
          "maxLength": 512
        },
        "description": "Opaque cursor from pagination.next_cursor. Bound to the sort it was issued for."
      },
      "IdempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": true,
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 128,
          "pattern": "^[A-Za-z0-9._:-]+$"
        },
        "description": "Unique, stable key per logical operation. Retrying with the same key and the same request replays the original response."
      },
      "IdempotencyKeyOptional": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string",
          "minLength": 8,
          "maxLength": 128,
          "pattern": "^[A-Za-z0-9._:-]+$"
        },
        "description": "Optional. A partial update with the same body converges to the same state; when supplied the key is honoured like on POST."
      }
    },
    "responses": {
      "BadAuth": {
        "description": "Missing, malformed, revoked, expired or unknown API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "Valid key, but the scope, role permission, purchased plan/app or Developer API entitlement does not allow this.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "No such resource inside the key's reach. Out-of-scope, foreign, malformed and unknown identifiers are indistinguishable.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Invalid": {
        "description": "Validation failed (unknown field, bad value, bad query parameter, reserved context field, missing/invalid Idempotency-Key, plan limit).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Conflict": {
        "description": "Business or idempotency conflict (see error.code).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Too many requests. Wait Retry-After seconds.",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "ServerError": {
        "description": "Unexpected server error. Safe to retry (writes are rolled back). Quote error.request_id to support.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    },
    "schemas": {
      "Error": {
        "type": "object",
        "required": [
          "error"
        ],
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "type",
              "code",
              "message",
              "request_id"
            ],
            "properties": {
              "type": {
                "type": "string",
                "description": "Broad category, e.g. authentication_error, permission_denied, validation_error, not_found, business_conflict, idempotency_error, rate_limited, server_error."
              },
              "code": {
                "type": "string",
                "description": "Stable machine-readable code. Branch on this, not on the message."
              },
              "message": {
                "type": "string"
              },
              "request_id": {
                "type": "string",
                "description": "Also returned in the X-Request-Id header. Quote it to support."
              },
              "details": {
                "type": "object",
                "additionalProperties": true,
                "description": "Present for validation errors: a map of field name to a list of messages."
              },
              "doc_url": {
                "type": "string",
                "format": "uri"
              }
            }
          }
        }
      },
      "Pagination": {
        "type": "object",
        "required": [
          "limit",
          "has_more",
          "next_cursor"
        ],
        "properties": {
          "limit": {
            "type": "integer"
          },
          "has_more": {
            "type": "boolean"
          },
          "next_cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as ?cursor= to fetch the next page. Null on the last page."
          }
        }
      },
      "Me": {
        "type": "object",
        "properties": {
          "key": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "prefix": {
                "type": "string"
              },
              "environment": {
                "type": "string",
                "enum": [
                  "live",
                  "test"
                ]
              },
              "scopes": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "expires_at": {
                "type": [
                  "string",
                  "null"
                ],
                "format": "date-time"
              }
            }
          },
          "tenant": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "slug": {
                "type": "string"
              }
            }
          },
          "company": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              },
              "code": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "hierarchy": {
            "type": "object",
            "properties": {
              "level": {
                "type": "string"
              },
              "name": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          },
          "role": {
            "type": "object",
            "properties": {
              "name": {
                "type": "string"
              }
            }
          },
          "rate_limits": {
            "type": "object",
            "properties": {
              "per_key_per_minute": {
                "type": "integer"
              },
              "per_tenant_per_minute": {
                "type": "integer"
              }
            }
          }
        }
      },
      "Node": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "nd_0123456789abcdef01234567"
            ]
          },
          "name": {
            "type": [
              "string",
              "null"
            ]
          },
          "level": {
            "type": "string",
            "enum": [
              "company",
              "bg",
              "le",
              "ou",
              "su"
            ]
          },
          "parent_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_self": {
            "type": "boolean"
          }
        }
      },
      "Lead": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "ld_0123456789abcdef01234567"
            ]
          },
          "first_name": {
            "type": "string"
          },
          "last_name": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "company_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "designation": {
            "type": [
              "string",
              "null"
            ]
          },
          "city": {
            "type": [
              "string",
              "null"
            ]
          },
          "country": {
            "type": [
              "string",
              "null"
            ]
          },
          "source": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": [
              "string",
              "null"
            ]
          },
          "lifecycle": {
            "type": "string",
            "enum": [
              "active",
              "converted",
              "invoice_generated",
              "archived"
            ]
          },
          "priority": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "urgent"
            ]
          },
          "score": {
            "type": [
              "integer",
              "null"
            ]
          },
          "is_hot": {
            "type": "boolean"
          },
          "node": {
            "type": [
              "string",
              "null"
            ]
          },
          "last_activity_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "Customer": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "cus_0123456789abcdef01234567"
            ]
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "address": {
            "type": [
              "string",
              "null"
            ]
          },
          "is_active": {
            "type": "boolean"
          },
          "node": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "Product": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "prd_0123456789abcdef01234567"
            ]
          },
          "sku": {
            "type": [
              "string",
              "null"
            ]
          },
          "barcode": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "type": {
            "type": "string",
            "enum": [
              "standard",
              "bundle"
            ]
          },
          "category": {
            "type": [
              "string",
              "null"
            ]
          },
          "sale_price": {
            "type": [
              "number",
              "null"
            ]
          },
          "is_active": {
            "type": "boolean"
          },
          "can_sell": {
            "type": "boolean"
          },
          "track_inventory": {
            "type": "boolean"
          },
          "node": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "Student": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "stu_0123456789abcdef01234567"
            ]
          },
          "code": {
            "type": [
              "string",
              "null"
            ]
          },
          "name": {
            "type": "string"
          },
          "status": {
            "type": "string"
          },
          "is_active": {
            "type": "boolean"
          },
          "class": {
            "type": [
              "string",
              "null"
            ]
          },
          "section": {
            "type": [
              "string",
              "null"
            ]
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "node": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "Invoice": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "examples": [
              "inv_0123456789abcdef01234567"
            ]
          },
          "number": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Invoice lifecycle status, e.g. draft, sent, viewed, partial, paid, overdue, void."
          },
          "payment_status": {
            "type": "string",
            "enum": [
              "paid",
              "partially_paid",
              "unpaid",
              "not_payable"
            ]
          },
          "currency": {
            "type": "string"
          },
          "issue_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "due_date": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "subtotal": {
            "type": "number"
          },
          "tax_amount": {
            "type": "number"
          },
          "discount_amount": {
            "type": "number"
          },
          "total": {
            "type": "number"
          },
          "amount_paid": {
            "type": "number"
          },
          "amount_due": {
            "type": "number"
          },
          "amount_credited": {
            "type": "number"
          },
          "amount_written_off": {
            "type": "number"
          },
          "customer_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "customer_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "paid_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "sent_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "node": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "updated_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "Subscription": {
        "type": "object",
        "properties": {
          "status": {
            "type": "string"
          },
          "billing_cycle": {
            "type": "string"
          },
          "currency": {
            "type": "string"
          },
          "price_amount": {
            "type": "number"
          },
          "current_period_start": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "current_period_end": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "trial_ends_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "cancel_at_period_end": {
            "type": "boolean"
          },
          "cancelled_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "apps": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "app": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "enum": [
                    "erp",
                    "crm",
                    "education",
                    null
                  ]
                },
                "tier": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "plan_slug": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "plan_name": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "billing_cycle": {
                  "type": "string"
                },
                "currency": {
                  "type": "string"
                },
                "unit_price": {
                  "type": "number"
                }
              }
            }
          }
        }
      },
      "PaymentLink": {
        "type": "object",
        "properties": {
          "invoice_id": {
            "type": "string"
          },
          "url": {
            "type": "string",
            "format": "uri"
          },
          "expires_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "CatalogPlan": {
        "type": "object",
        "properties": {
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "tier": {
            "type": "string"
          },
          "most_popular": {
            "type": "boolean"
          },
          "available": {
            "type": "boolean"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "features": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "trial_days": {
            "type": "integer"
          },
          "billing_periods": {
            "type": "array",
            "items": {
              "type": "string",
              "enum": [
                "monthly",
                "yearly"
              ]
            }
          },
          "currencies": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "prices": {
            "type": "object",
            "description": "period -> currency -> amount. Each cell is an independently configured price; never convert between cells.",
            "additionalProperties": {
              "type": "object",
              "additionalProperties": {
                "type": "number"
              }
            }
          },
          "limits": {
            "type": "object",
            "description": "Resource limits. null means unlimited.",
            "additionalProperties": {
              "type": [
                "integer",
                "null"
              ]
            }
          }
        }
      },
      "Catalog": {
        "type": "object",
        "properties": {
          "apps": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "code": {
                  "type": "string",
                  "enum": [
                    "erp",
                    "crm",
                    "education"
                  ]
                },
                "name": {
                  "type": "string"
                },
                "plans": {
                  "type": "array",
                  "items": {
                    "$ref": "#/components/schemas/CatalogPlan"
                  }
                }
              }
            }
          },
          "billing": {
            "type": "object",
            "properties": {
              "periods": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              },
              "currencies": {
                "type": "array",
                "items": {
                  "type": "string"
                }
              }
            }
          },
          "subscription_rules": {
            "type": "object",
            "properties": {
              "multiple_apps": {
                "type": "boolean"
              },
              "one_billing_period": {
                "type": "boolean"
              },
              "one_currency": {
                "type": "boolean"
              },
              "one_plan_per_app": {
                "type": "boolean"
              }
            }
          }
        }
      },
      "LeadCreate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "first_name",
          "last_name",
          "email",
          "phone",
          "source"
        ],
        "properties": {
          "first_name": {
            "type": "string",
            "maxLength": 100
          },
          "last_name": {
            "type": "string",
            "maxLength": 100
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 255
          },
          "phone": {
            "type": "string",
            "maxLength": 30
          },
          "secondary_phone": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 30
          },
          "company_name": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "designation": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "website": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "maxLength": 255
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2000
          },
          "city": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100
          },
          "state": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100
          },
          "country": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100
          },
          "priority": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "urgent"
            ],
            "default": "medium"
          },
          "source": {
            "type": "string",
            "maxLength": 255,
            "description": "Lead source NAME as configured in your CRM."
          },
          "status": {
            "type": "string",
            "maxLength": 255
          },
          "node": {
            "type": "string",
            "maxLength": 64,
            "description": "Public node reference (nd_...). Must be inside the key's own hierarchy subtree; defaults to the key's own node."
          }
        }
      },
      "LeadUpdate": {
        "type": "object",
        "additionalProperties": false,
        "required": [],
        "properties": {
          "first_name": {
            "type": "string",
            "maxLength": 100
          },
          "last_name": {
            "type": "string",
            "maxLength": 100
          },
          "email": {
            "type": "string",
            "format": "email",
            "maxLength": 255
          },
          "phone": {
            "type": "string",
            "maxLength": 30
          },
          "secondary_phone": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 30
          },
          "company_name": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "designation": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 255
          },
          "website": {
            "type": [
              "string",
              "null"
            ],
            "format": "uri",
            "maxLength": 255
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2000
          },
          "city": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100
          },
          "state": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100
          },
          "country": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 100
          },
          "priority": {
            "type": "string",
            "enum": [
              "low",
              "medium",
              "high",
              "urgent"
            ]
          }
        }
      },
      "CustomerCreate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email",
            "maxLength": 255
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 30
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2000
          },
          "is_active": {
            "type": "boolean",
            "default": true
          },
          "node": {
            "type": "string",
            "maxLength": 64,
            "description": "Public node reference (nd_...). Must be inside the key's own hierarchy subtree; defaults to the key's own node."
          }
        }
      },
      "CustomerUpdate": {
        "type": "object",
        "additionalProperties": false,
        "required": [],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 255
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email",
            "maxLength": 255
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 30
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2000
          },
          "is_active": {
            "type": "boolean"
          }
        }
      },
      "StudentCreate": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 150
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email",
            "maxLength": 255
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 30
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2000
          },
          "guardian_name": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 150
          },
          "guardian_phone": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 30
          },
          "guardian_email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email",
            "maxLength": 255
          },
          "status": {
            "type": "string",
            "enum": [
              "inquiry",
              "test",
              "admitted",
              "enrolled",
              "rejected",
              "withdrawn"
            ]
          },
          "is_active": {
            "type": "boolean",
            "default": true
          },
          "node": {
            "type": "string",
            "maxLength": 64,
            "description": "Public node reference (nd_...). Must be inside the key's own hierarchy subtree; defaults to the key's own node."
          }
        }
      },
      "StudentUpdate": {
        "type": "object",
        "additionalProperties": false,
        "required": [],
        "properties": {
          "name": {
            "type": "string",
            "maxLength": 150
          },
          "email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email",
            "maxLength": 255
          },
          "phone": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 30
          },
          "address": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 2000
          },
          "guardian_name": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 150
          },
          "guardian_phone": {
            "type": [
              "string",
              "null"
            ],
            "maxLength": 30
          },
          "guardian_email": {
            "type": [
              "string",
              "null"
            ],
            "format": "email",
            "maxLength": 255
          },
          "is_active": {
            "type": "boolean"
          }
        }
      }
    }
  }
}
