{
  "openapi": "3.1.0",
  "info": {
    "title": "Jibrid API",
    "description": "ZATCA e-invoicing, Qoyod accounting, and Foodics POS API for Saudi Arabia. Submit ZATCA-compliant invoices, sync accounting data with Qoyod, and access Foodics POS data — all through simple JSON API calls.",
    "version": "1.0.0",
    "contact": {
      "name": "Jibrid API Support",
      "email": "api@jibrid.com",
      "url": "https://www.jibrid.com"
    },
    "license": {
      "name": "Proprietary"
    },
    "x-llm-description": "Jibrid is an API that handles ZATCA (Saudi Arabia tax authority) e-invoicing compliance, Qoyod accounting integration, and Foodics POS data. It lets you onboard with ZATCA, submit invoices, sync accounting data with Qoyod, access Foodics branches/products/orders/customers — all through simple JSON API calls."
  },
  "servers": [
    {
      "url": "https://www.jibrid.com/api",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    }
  ],
  "tags": [
    {
      "name": "Onboarding",
      "description": "Register your organization with ZATCA. This must be done once before submitting invoices.",
      "x-llm-description": "Use the onboarding endpoint to connect an organization to ZATCA. You need the organization's VAT number and an OTP from the ZATCA FATOORA portal. For sandbox testing, the OTP is always '123456'."
    },
    {
      "name": "Invoices",
      "description": "Submit, list, and retrieve ZATCA-compliant e-invoices.",
      "x-llm-description": "Use these endpoints to submit invoices to ZATCA. Simplified invoices (B2C) go through 'reporting' and return REPORTED status. Standard invoices (B2B) go through 'clearance' and return CLEARED status. The API handles XML generation, digital signing, QR code generation, and hash computation."
    },
    {
      "name": "Status",
      "description": "Check ZATCA connection health and invoice statistics.",
      "x-llm-description": "Use the status endpoint to verify that ZATCA onboarding is active and to get invoice submission statistics."
    },
    {
      "name": "Qoyod",
      "description": "Sync accounting data with Qoyod — chart of accounts, customers, invoices, and products.",
      "x-llm-description": "Use Qoyod endpoints to read and write accounting data to/from the connected Qoyod organization. The Qoyod connection must be established first via the dashboard. All Qoyod endpoints use the same API key authentication as ZATCA endpoints."
    },
    {
      "name": "Foodics",
      "description": "POS integration — branches, products, categories, orders, and customers from Foodics.",
      "x-llm-description": "Use Foodics endpoints to read POS data from the connected Foodics account. Access branches, menu products, categories, orders, and customers. The Foodics connection must be established first via the dashboard OAuth flow. All Foodics endpoints use the same API key authentication as ZATCA and Qoyod endpoints."
    }
  ],
  "paths": {
    "/v1/zatca/onboard": {
      "post": {
        "operationId": "onboardOrganization",
        "summary": "Onboard organization with ZATCA",
        "description": "Complete ZATCA e-invoicing onboarding in one request. Generates a cryptographic key pair, creates a CSR, obtains compliance and production certificates from ZATCA, and stores encrypted credentials. This must be called once before submitting invoices.",
        "x-llm-description": "Call this endpoint once to register an organization with ZATCA. You need the 15-digit VAT number (starts and ends with 3) and an OTP from the ZATCA FATOORA portal. For sandbox/testing, use OTP '123456'. The process takes 5-15 seconds as it communicates with ZATCA servers.",
        "tags": ["Onboarding"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/OnboardRequest"
              },
              "example": {
                "org_name": "Acme Trading LLC",
                "vat_number": "399999999900003",
                "otp": "123456",
                "city": "Riyadh",
                "org_unit": "Main Branch"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Onboarding successful. Organization is now connected to ZATCA.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/OnboardResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "onboarding_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                    "status": "active",
                    "vat_number": "399999999900003",
                    "egs_serial": "1-Jibrid|2-1.0|3-f47ac10b-58cc-4372-a567-0e02b2c3d479",
                    "environment": "sandbox",
                    "duration_ms": 8432
                  },
                  "meta": {
                    "request_id": "req_abc123def456",
                    "timestamp": "2025-01-15T10:30:00.000Z",
                    "environment": "sandbox"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error — invalid VAT number, missing fields, or invalid OTP.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "INVALID_VAT_NUMBER",
                    "message": "VAT number must be exactly 15 digits",
                    "message_ar": "الرقم الضريبي يجب أن يكون 15 رقم"
                  },
                  "meta": {
                    "request_id": "req_xyz789",
                    "timestamp": "2025-01-15T10:30:00.000Z",
                    "environment": "sandbox"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "description": "Onboarding failed — ZATCA rejected the CSR or compliance check.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "ONBOARDING_FAILED",
                    "message": "ZATCA API error 400: Invalid Request",
                    "message_ar": "فشل التسجيل في فاتورة"
                  },
                  "meta": {
                    "request_id": "req_xyz789",
                    "timestamp": "2025-01-15T10:30:00.000Z",
                    "environment": "sandbox"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/zatca/invoices": {
      "post": {
        "operationId": "submitInvoice",
        "summary": "Submit a ZATCA-compliant e-invoice",
        "description": "Generate UBL 2.1 XML, digitally sign it, compute the invoice hash and QR code, and submit to ZATCA for reporting (simplified/B2C) or clearance (standard/B2B). VAT amounts are calculated server-side. The organization must be onboarded first via POST /v1/zatca/onboard.",
        "x-llm-description": "Submit an invoice to ZATCA. For simplified invoices (B2C, cash sales), set invoice_type to 'simplified' — these are reported to ZATCA and get REPORTED status. For standard invoices (B2B, business-to-business), set invoice_type to 'standard' and include buyer details — these require ZATCA clearance and get CLEARED status. You only provide item names, quantities, unit prices, and VAT rates. The API calculates all totals, generates the XML, signs it, and submits to ZATCA.",
        "tags": ["Invoices"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/InvoiceRequest"
              },
              "examples": {
                "simplified": {
                  "summary": "Simplified invoice (B2C)",
                  "value": {
                    "invoice_type": "simplified",
                    "invoice_number": "INV-2025-001",
                    "issue_date": "2025-01-15",
                    "issue_time": "14:30:00",
                    "seller": {
                      "vat_number": "399999999900003",
                      "name": "Acme Trading LLC",
                      "address": {
                        "street": "King Fahd Road",
                        "building_number": "2929",
                        "city": "Riyadh",
                        "district": "Al Olaya",
                        "postal_code": "12345"
                      }
                    },
                    "items": [
                      {
                        "name": "Web Development Service",
                        "quantity": 1,
                        "unit_price": 1000,
                        "vat_rate": 0.15
                      }
                    ],
                    "payment_means": "10"
                  }
                },
                "standard": {
                  "summary": "Standard invoice (B2B)",
                  "value": {
                    "invoice_type": "standard",
                    "invoice_number": "INV-2025-002",
                    "issue_date": "2025-01-15",
                    "issue_time": "14:30:00",
                    "seller": {
                      "vat_number": "399999999900003",
                      "name": "Acme Trading LLC",
                      "commercial_registration": "1010123456",
                      "address": {
                        "street": "King Fahd Road",
                        "building_number": "2929",
                        "city": "Riyadh",
                        "district": "Al Olaya",
                        "postal_code": "12345"
                      }
                    },
                    "buyer": {
                      "vat_number": "399999999800003",
                      "name": "Buyer Company Ltd",
                      "address": {
                        "street": "Olaya Street",
                        "building_number": "3456",
                        "city": "Riyadh",
                        "district": "Al Olaya",
                        "postal_code": "11564"
                      }
                    },
                    "items": [
                      {
                        "name": "Annual SaaS License",
                        "quantity": 1,
                        "unit_price": 50000,
                        "vat_rate": 0.15
                      },
                      {
                        "name": "Implementation & Setup",
                        "quantity": 1,
                        "unit_price": 15000,
                        "vat_rate": 0.15
                      }
                    ],
                    "payment_means": "30"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "201": {
            "description": "Invoice submitted successfully. Check `status` field for ZATCA result.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "invoice_id": "0cbbe98b-cd11-4757-a722-6a82b4725fbc",
                    "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                    "invoice_number": "INV-2025-001",
                    "status": "REPORTED",
                    "reporting_status": "REPORTED",
                    "clearance_status": null,
                    "invoice_hash": "dGVzdCBoYXNoIHZhbHVl...",
                    "qr_code": "AQlBY21lIFRyYWRpbmcgTExDAg8zOTk5OTk5OTk5MDAw...",
                    "validation_results": {
                      "status": "WARNING",
                      "errors": [],
                      "warnings": [
                        {
                          "type": "WARNING",
                          "code": "BR-KSA-F-13",
                          "message": "Please recheck Other Seller/Buyer ID"
                        }
                      ]
                    },
                    "totals": {
                      "subtotal": 1000,
                      "vat_total": 150,
                      "total": 1150,
                      "currency": "SAR"
                    }
                  },
                  "meta": {
                    "request_id": "req_abc123def456",
                    "timestamp": "2025-01-15T14:30:05.000Z",
                    "environment": "sandbox"
                  }
                }
              }
            }
          },
          "400": {
            "description": "Validation error — missing fields, invalid date format, or not onboarded.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "examples": {
                  "not_onboarded": {
                    "summary": "Organization not onboarded",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "NOT_ONBOARDED",
                        "message": "No active ZATCA credentials found. Call POST /v1/zatca/onboard first.",
                        "message_ar": "لم يتم التسجيل في فاتورة بعد. استخدم /v1/zatca/onboard أولاً"
                      },
                      "meta": {
                        "request_id": "req_xyz789",
                        "timestamp": "2025-01-15T14:30:00.000Z",
                        "environment": "sandbox"
                      }
                    }
                  },
                  "missing_field": {
                    "summary": "Missing required field",
                    "value": {
                      "success": false,
                      "error": {
                        "code": "MISSING_FIELD",
                        "message": "invoice_number is required",
                        "message_ar": "رقم الفاتورة مطلوب"
                      },
                      "meta": {
                        "request_id": "req_xyz789",
                        "timestamp": "2025-01-15T14:30:00.000Z",
                        "environment": "sandbox"
                      }
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "description": "Invoice submission failed — ZATCA rejected the invoice or internal error.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      },
      "get": {
        "operationId": "listInvoices",
        "summary": "List submitted invoices",
        "description": "Retrieve a paginated list of all invoices submitted by this organization, sorted by creation date (newest first).",
        "x-llm-description": "List all invoices for the authenticated organization. Supports pagination with page and limit query parameters. Returns invoice summaries including ZATCA status, totals, and hashes. Default page size is 20, maximum is 100.",
        "tags": ["Invoices"],
        "parameters": [
          {
            "name": "page",
            "in": "query",
            "description": "Page number (1-indexed). Defaults to 1.",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "default": 1
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Number of invoices per page. Defaults to 20, maximum 100.",
            "required": false,
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 20
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Paginated list of invoices.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceListResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "invoices": [
                      {
                        "id": "0cbbe98b-cd11-4757-a722-6a82b4725fbc",
                        "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                        "invoice_number": "INV-2025-001",
                        "invoice_type": "simplified",
                        "subtotal": 1000,
                        "vat_total": 150,
                        "total": 1150,
                        "currency": "SAR",
                        "zatca_status": "REPORTED",
                        "reporting_status": "REPORTED",
                        "clearance_status": null,
                        "validation_status": "WARNING",
                        "invoice_hash": "dGVzdCBoYXNo...",
                        "qr_code": "AQlBY21l...",
                        "issue_date": "2025-01-15",
                        "issue_time": "14:30:00",
                        "created_at": "2025-01-15T14:30:05.000Z"
                      }
                    ],
                    "pagination": {
                      "page": 1,
                      "limit": 20,
                      "total": 1,
                      "total_pages": 1
                    }
                  },
                  "meta": {
                    "request_id": "req_abc123def456",
                    "timestamp": "2025-01-15T14:31:00.000Z",
                    "environment": "sandbox"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "500": {
            "description": "Failed to retrieve invoices.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/zatca/invoices/{id}": {
      "get": {
        "operationId": "getInvoice",
        "summary": "Get invoice detail",
        "description": "Retrieve the full details of a specific invoice including ZATCA validation results, signed XML, QR code, and the original request payload.",
        "x-llm-description": "Get the full details of a submitted invoice by its ID (UUID). Returns all ZATCA response data including validation errors/warnings, the invoice hash, QR code, and the complete original request payload.",
        "tags": ["Invoices"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Invoice ID (UUID) returned from the submit endpoint.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Full invoice detail.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/InvoiceDetailResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "invoice": {
                      "id": "0cbbe98b-cd11-4757-a722-6a82b4725fbc",
                      "uuid": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
                      "invoice_number": "INV-2025-001",
                      "invoice_type": "simplified",
                      "invoice_counter": 1,
                      "subtotal": 1000,
                      "vat_total": 150,
                      "total": 1150,
                      "currency": "SAR",
                      "zatca_status": "REPORTED",
                      "reporting_status": "REPORTED",
                      "clearance_status": null,
                      "validation_status": "WARNING",
                      "validation_errors": [],
                      "validation_warnings": [
                        {
                          "type": "WARNING",
                          "code": "BR-KSA-F-13",
                          "message": "Please recheck Other Seller/Buyer ID"
                        }
                      ],
                      "invoice_hash": "dGVzdCBoYXNoIHZhbHVl...",
                      "qr_code": "AQlBY21lIFRyYWRpbmcgTExDAg8zOTk5OTk5OTk5MDAw...",
                      "issue_date": "2025-01-15",
                      "issue_time": "14:30:00",
                      "request_payload": {
                        "invoice_type": "simplified",
                        "invoice_number": "INV-2025-001",
                        "seller": { "name": "Acme Trading LLC" }
                      },
                      "created_at": "2025-01-15T14:30:05.000Z"
                    }
                  },
                  "meta": {
                    "request_id": "req_abc123def456",
                    "timestamp": "2025-01-15T14:31:00.000Z",
                    "environment": "sandbox"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "404": {
            "description": "Invoice not found or does not belong to this organization.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                },
                "example": {
                  "success": false,
                  "error": {
                    "code": "NOT_FOUND",
                    "message": "Invoice not found",
                    "message_ar": "الفاتورة غير موجودة"
                  },
                  "meta": {
                    "request_id": "req_xyz789",
                    "timestamp": "2025-01-15T14:31:00.000Z",
                    "environment": "sandbox"
                  }
                }
              }
            }
          }
        }
      }
    },
    "/v1/zatca/status": {
      "get": {
        "operationId": "getStatus",
        "summary": "Check ZATCA connection status",
        "description": "Returns the ZATCA onboarding status, credential health, invoice submission statistics for the last 30 days, and the current API plan and rate limit.",
        "x-llm-description": "Check if the organization is onboarded with ZATCA and get invoice statistics. The response includes onboarding status ('active' or 'not_onboarded'), total invoice count, invoices submitted in the last 30 days, and error count. Also returns the current API plan and rate limit.",
        "tags": ["Status"],
        "responses": {
          "200": {
            "description": "ZATCA connection status and statistics.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StatusResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "onboarding": {
                      "status": "active",
                      "vat_number": "399999999900003",
                      "egs_serial": "1-Jibrid|2-1.0|3-f47ac10b-58cc-4372-a567-0e02b2c3d479",
                      "environment": "sandbox",
                      "onboarded_at": "2025-01-10T08:00:00.000Z",
                      "expires_at": null
                    },
                    "stats": {
                      "total_invoices": 42,
                      "last_30_days": 15,
                      "errors_last_30_days": 0
                    },
                    "plan": "free",
                    "rate_limit_per_minute": 60
                  },
                  "meta": {
                    "request_id": "req_abc123def456",
                    "timestamp": "2025-01-15T14:32:00.000Z",
                    "environment": "sandbox"
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          }
        }
      }
    },
    "/v1/qoyod/status": {
      "get": {
        "operationId": "getQoyodStatus",
        "summary": "Check Qoyod connection status",
        "description": "Returns whether the Qoyod accounting integration is connected for the authenticated organization.",
        "x-llm-description": "Check if Qoyod is connected. Returns { connected: true/false }. If not connected, the user must connect via the Jibrid dashboard first.",
        "tags": ["Qoyod"],
        "responses": {
          "200": {
            "description": "Qoyod connection status.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QoyodStatusResponse"
                },
                "example": {
                  "success": true,
                  "data": { "connected": true, "connector": "qoyod" },
                  "meta": { "request_id": "req_abc123", "timestamp": "2026-02-21T12:00:00.000Z", "environment": "sandbox" }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/qoyod/accounts": {
      "get": {
        "operationId": "listQoyodAccounts",
        "summary": "List chart of accounts",
        "description": "Retrieve the full chart of accounts from the connected Qoyod organization. Returns account names (English and Arabic), codes, types, and active status.",
        "x-llm-description": "Get all accounts from Qoyod. Each account has an id, name, optional name_ar (Arabic), code, account_type (asset, liability, equity, revenue, expense), parent_id, and is_active flag.",
        "tags": ["Qoyod"],
        "responses": {
          "200": {
            "description": "List of accounts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/QoyodAccountsResponse"
                },
                "example": {
                  "success": true,
                  "data": {
                    "accounts": [
                      { "id": 1, "name": "Cash", "name_ar": "نقد", "code": "1001", "account_type": "asset", "parent_id": null, "is_active": true }
                    ]
                  },
                  "meta": { "request_id": "req_abc123", "timestamp": "2026-02-21T12:00:00.000Z", "environment": "sandbox" }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": {
            "description": "Qoyod not connected.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/ErrorResponse" },
                "example": {
                  "success": false,
                  "error": { "code": "QOYOD_NOT_CONNECTED", "message": "Qoyod is not connected. Connect via the dashboard first.", "message_ar": "لم يتم ربط Qoyod بعد. اربط الحساب من لوحة التحكم" },
                  "meta": { "request_id": "req_xyz789", "timestamp": "2026-02-21T12:00:00.000Z", "environment": "sandbox" }
                }
              }
            }
          }
        }
      }
    },
    "/v1/qoyod/customers": {
      "get": {
        "operationId": "listQoyodCustomers",
        "summary": "List customers",
        "description": "Retrieve a paginated list of customers from the connected Qoyod organization.",
        "x-llm-description": "List customers from Qoyod. Supports pagination with page and per_page query parameters.",
        "tags": ["Qoyod"],
        "parameters": [
          { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "default": 1 }, "description": "Page number." },
          { "name": "per_page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "default": 20 }, "description": "Results per page." }
        ],
        "responses": {
          "200": {
            "description": "List of customers.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/QoyodCustomersResponse" },
                "example": {
                  "success": true,
                  "data": {
                    "customers": [
                      { "id": 1, "name": "Acme Corp", "email": "info@acme.sa", "vat_number": "300000000000003" }
                    ]
                  },
                  "meta": { "request_id": "req_abc123", "timestamp": "2026-02-21T12:00:00.000Z", "environment": "sandbox" }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": {
            "description": "Qoyod not connected.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
          }
        }
      },
      "post": {
        "operationId": "createQoyodCustomer",
        "summary": "Create a customer",
        "description": "Create a new customer in the connected Qoyod organization.",
        "x-llm-description": "Create a customer in Qoyod. Only the name field is required. Optionally include email, phone, vat_number, address, city, and country.",
        "tags": ["Qoyod"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/QoyodCreateCustomerRequest" },
              "example": {
                "name": "Acme Corp",
                "email": "info@acme.sa",
                "vat_number": "300000000000003"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Customer created.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/QoyodCustomerResponse" },
                "example": {
                  "success": true,
                  "data": {
                    "customer": { "id": 42, "name": "Acme Corp", "email": "info@acme.sa", "vat_number": "300000000000003" }
                  },
                  "meta": { "request_id": "req_abc123", "timestamp": "2026-02-21T12:00:00.000Z", "environment": "sandbox" }
                }
              }
            }
          },
          "400": {
            "description": "Validation error.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": {
            "description": "Qoyod not connected.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
          }
        }
      }
    },
    "/v1/qoyod/invoices": {
      "get": {
        "operationId": "listQoyodInvoices",
        "summary": "List invoices",
        "description": "Retrieve a paginated list of invoices from the connected Qoyod organization.",
        "x-llm-description": "List invoices from Qoyod. Supports pagination with page and per_page query parameters.",
        "tags": ["Qoyod"],
        "parameters": [
          { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "default": 1 }, "description": "Page number." },
          { "name": "per_page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "default": 20 }, "description": "Results per page." }
        ],
        "responses": {
          "200": {
            "description": "List of invoices.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/QoyodInvoicesResponse" },
                "example": {
                  "success": true,
                  "data": {
                    "invoices": [
                      { "id": 1, "reference": "INV-001", "customer_id": 42, "date": "2026-02-21", "status": "sent", "total": 1150 }
                    ]
                  },
                  "meta": { "request_id": "req_abc123", "timestamp": "2026-02-21T12:00:00.000Z", "environment": "sandbox" }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": {
            "description": "Qoyod not connected.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
          }
        }
      },
      "post": {
        "operationId": "createQoyodInvoice",
        "summary": "Create an invoice",
        "description": "Create a new invoice in the connected Qoyod organization. Provide either customer_id (existing Qoyod customer) or customer_name (inline).",
        "x-llm-description": "Create an invoice in Qoyod. Required fields: date and line_items. Must provide either customer_id or customer_name. Each line item needs description, quantity, and unit_price. Optionally include tax_rate (percentage, e.g. 15) and product_id.",
        "tags": ["Qoyod"],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": { "$ref": "#/components/schemas/QoyodCreateInvoiceRequest" },
              "example": {
                "customer_id": 42,
                "date": "2026-02-21",
                "due_date": "2026-03-21",
                "reference": "INV-001",
                "notes": "Monthly service fee",
                "line_items": [
                  { "description": "Web Development", "quantity": 1, "unit_price": 1000, "tax_rate": 15 }
                ]
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Invoice created.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/QoyodInvoiceResponse" },
                "example": {
                  "success": true,
                  "data": {
                    "invoice": {
                      "id": 1, "reference": "INV-001", "customer_id": 42, "date": "2026-02-21",
                      "status": "draft", "subtotal": 1000, "tax_total": 150, "total": 1150
                    }
                  },
                  "meta": { "request_id": "req_abc123", "timestamp": "2026-02-21T12:00:00.000Z", "environment": "sandbox" }
                }
              }
            }
          },
          "400": {
            "description": "Validation error — missing date, line_items, or customer identifier.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": {
            "description": "Qoyod not connected.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
          }
        }
      }
    },
    "/v1/qoyod/invoices/{id}": {
      "get": {
        "operationId": "getQoyodInvoice",
        "summary": "Get invoice detail",
        "description": "Retrieve the full details of a specific Qoyod invoice by its numeric ID, including line items and totals.",
        "x-llm-description": "Get a single invoice from Qoyod by its numeric ID. Returns the full invoice including line items, totals, and customer reference.",
        "tags": ["Qoyod"],
        "parameters": [
          {
            "name": "id",
            "in": "path",
            "required": true,
            "description": "Qoyod invoice ID (numeric).",
            "schema": { "type": "integer" }
          }
        ],
        "responses": {
          "200": {
            "description": "Invoice detail.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/QoyodInvoiceResponse" }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "404": {
            "description": "Invoice not found in Qoyod.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
          },
          "422": {
            "description": "Qoyod not connected.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
          }
        }
      }
    },
    "/v1/qoyod/products": {
      "get": {
        "operationId": "listQoyodProducts",
        "summary": "List products",
        "description": "Retrieve all products from the connected Qoyod organization, including names (English and Arabic), SKU, price, and tax rate.",
        "x-llm-description": "List products from Qoyod. Each product has id, name, optional name_ar, sku, price, tax_rate, and is_active flag. Supports pagination.",
        "tags": ["Qoyod"],
        "parameters": [
          { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "default": 1 }, "description": "Page number." },
          { "name": "per_page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "default": 20 }, "description": "Results per page." }
        ],
        "responses": {
          "200": {
            "description": "List of products.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/QoyodProductsResponse" },
                "example": {
                  "success": true,
                  "data": {
                    "products": [
                      { "id": 1, "name": "Widget", "name_ar": "قطعة", "sku": "WDG-01", "price": 99.99, "tax_rate": 15, "is_active": true }
                    ]
                  },
                  "meta": { "request_id": "req_abc123", "timestamp": "2026-02-21T12:00:00.000Z", "environment": "sandbox" }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": {
            "description": "Qoyod not connected.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } }
          }
        }
      }
    },
    "/v1/foodics/status": {
      "get": {
        "operationId": "getFoodicsStatus",
        "summary": "Check Foodics connection status",
        "description": "Returns whether the Foodics POS integration is connected for the authenticated organization.",
        "x-llm-description": "Check if Foodics is connected. Returns connection status and plan info. If not connected, the user must connect via the Jibrid dashboard OAuth flow first.",
        "tags": ["Foodics"],
        "responses": {
          "200": {
            "description": "Foodics connection status.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/FoodicsStatusResponse" },
                "example": {
                  "success": true,
                  "data": { "connection": { "status": "connected", "connector": "foodics" }, "plan": "free", "rate_limit_per_minute": 60 },
                  "meta": { "request_id": "req_abc123", "timestamp": "2026-02-24T12:00:00.000Z", "environment": "sandbox" }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" }
        }
      }
    },
    "/v1/foodics/branches": {
      "get": {
        "operationId": "listFoodicsBranches",
        "summary": "List branches",
        "description": "Retrieve a paginated list of branches (store locations) from the connected Foodics account.",
        "x-llm-description": "List branches from Foodics. Each branch has id, name, name_ar, reference, phone, address, city, and is_active. Supports pagination and active status filtering.",
        "tags": ["Foodics"],
        "parameters": [
          { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "default": 1 }, "description": "Page number." },
          { "name": "page_size", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 25 }, "description": "Results per page (max 50)." },
          { "name": "is_active", "in": "query", "required": false, "schema": { "type": "boolean" }, "description": "Filter by active status." }
        ],
        "responses": {
          "200": {
            "description": "List of branches.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/FoodicsBranchesResponse" },
                "example": {
                  "success": true,
                  "data": {
                    "branches": [{ "id": "abc123", "name": "Main Branch", "name_ar": "الفرع الرئيسي", "reference": "001", "phone": "+966501234567", "address": "King Fahd Rd", "city": "Riyadh", "is_active": true }],
                    "pagination": { "page": 1, "total_pages": 1, "total_count": 1 }
                  },
                  "meta": { "request_id": "req_abc123", "timestamp": "2026-02-24T12:00:00.000Z", "environment": "sandbox" }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": { "description": "Foodics not connected.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },
    "/v1/foodics/branches/{id}": {
      "get": {
        "operationId": "getFoodicsBranch",
        "summary": "Get branch",
        "description": "Retrieve details of a specific Foodics branch by its HID.",
        "tags": ["Foodics"],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "description": "Foodics branch HID.", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Branch detail.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FoodicsBranchResponse" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": { "description": "Foodics not connected.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },
    "/v1/foodics/products": {
      "get": {
        "operationId": "listFoodicsProducts",
        "summary": "List products",
        "description": "Retrieve a paginated list of products (menu items) from the connected Foodics account.",
        "x-llm-description": "List products from Foodics. Each product has id, name, name_ar, sku, price, category_id, and is_active. Supports pagination, category filtering, active status filtering, and search.",
        "tags": ["Foodics"],
        "parameters": [
          { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "default": 1 }, "description": "Page number." },
          { "name": "page_size", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 25 }, "description": "Results per page (max 50)." },
          { "name": "category_id", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by category HID." },
          { "name": "is_active", "in": "query", "required": false, "schema": { "type": "boolean" }, "description": "Filter by active status." },
          { "name": "search", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Search by product name." }
        ],
        "responses": {
          "200": {
            "description": "List of products.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/FoodicsProductsResponse" },
                "example": {
                  "success": true,
                  "data": {
                    "products": [{ "id": "prod123", "name": "Chicken Burger", "name_ar": "برجر دجاج", "sku": "CB-01", "price": 25, "category_id": "cat456", "is_active": true }],
                    "pagination": { "page": 1, "total_pages": 1, "total_count": 1 }
                  },
                  "meta": { "request_id": "req_abc123", "timestamp": "2026-02-24T12:00:00.000Z", "environment": "sandbox" }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": { "description": "Foodics not connected.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },
    "/v1/foodics/products/{id}": {
      "get": {
        "operationId": "getFoodicsProduct",
        "summary": "Get product",
        "description": "Retrieve details of a specific Foodics product by its HID.",
        "tags": ["Foodics"],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "description": "Foodics product HID.", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Product detail.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FoodicsProductResponse" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": { "description": "Foodics not connected.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },
    "/v1/foodics/categories": {
      "get": {
        "operationId": "listFoodicsCategories",
        "summary": "List categories",
        "description": "Retrieve a paginated list of product categories from the connected Foodics account.",
        "x-llm-description": "List product categories from Foodics. Each category has id, name, name_ar, parent_id, and is_active.",
        "tags": ["Foodics"],
        "parameters": [
          { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "default": 1 }, "description": "Page number." },
          { "name": "page_size", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 25 }, "description": "Results per page (max 50)." },
          { "name": "is_active", "in": "query", "required": false, "schema": { "type": "boolean" }, "description": "Filter by active status." }
        ],
        "responses": {
          "200": {
            "description": "List of categories.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/FoodicsCategoriesResponse" },
                "example": {
                  "success": true,
                  "data": {
                    "categories": [{ "id": "cat456", "name": "Burgers", "name_ar": "برجر", "parent_id": null, "is_active": true }],
                    "pagination": { "page": 1, "total_pages": 1, "total_count": 1 }
                  },
                  "meta": { "request_id": "req_abc123", "timestamp": "2026-02-24T12:00:00.000Z", "environment": "sandbox" }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": { "description": "Foodics not connected.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },
    "/v1/foodics/orders": {
      "get": {
        "operationId": "listFoodicsOrders",
        "summary": "List orders",
        "description": "Retrieve a paginated list of orders from the connected Foodics account. Supports filtering by branch, date range, and status.",
        "x-llm-description": "List orders from Foodics. Each order includes id, number, branch_id, customer_id, type, status, subtotal, discount, total, taxes, line_items, payments, and business_date. Use include=products,payments to get full details.",
        "tags": ["Foodics"],
        "parameters": [
          { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "default": 1 }, "description": "Page number." },
          { "name": "page_size", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 25 }, "description": "Results per page (max 50)." },
          { "name": "branch_id", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Filter by branch HID." },
          { "name": "date_from", "in": "query", "required": false, "schema": { "type": "string", "format": "date" }, "description": "Filter orders from this date (YYYY-MM-DD)." },
          { "name": "date_to", "in": "query", "required": false, "schema": { "type": "string", "format": "date" }, "description": "Filter orders to this date (YYYY-MM-DD)." },
          { "name": "status", "in": "query", "required": false, "schema": { "type": "string", "enum": ["closed", "void", "returned"] }, "description": "Filter by order status." },
          { "name": "include", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Include related resources (comma-separated: products, payments)." }
        ],
        "responses": {
          "200": {
            "description": "List of orders.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/FoodicsOrdersResponse" },
                "example": {
                  "success": true,
                  "data": {
                    "orders": [{ "id": "ord789", "number": 1001, "branch_id": "abc123", "customer_id": null, "type": "dine_in", "status": "closed", "subtotal": 50, "discount": 0, "total": 57.5, "taxes": [{ "name": "VAT", "rate": 15, "amount": 7.5 }], "line_items": [], "payments": [], "business_date": "2026-02-24", "created_at": "2026-02-24T14:00:00.000Z" }],
                    "pagination": { "page": 1, "total_pages": 1, "total_count": 1 }
                  },
                  "meta": { "request_id": "req_abc123", "timestamp": "2026-02-24T12:00:00.000Z", "environment": "sandbox" }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": { "description": "Foodics not connected.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },
    "/v1/foodics/orders/{id}": {
      "get": {
        "operationId": "getFoodicsOrder",
        "summary": "Get order",
        "description": "Retrieve full details of a specific Foodics order by its HID, including line items, payments, and taxes.",
        "tags": ["Foodics"],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "description": "Foodics order HID.", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Order detail.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FoodicsOrderResponse" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": { "description": "Foodics not connected.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },
    "/v1/foodics/customers": {
      "get": {
        "operationId": "listFoodicsCustomers",
        "summary": "List customers",
        "description": "Retrieve a paginated list of customers from the connected Foodics account.",
        "x-llm-description": "List customers from Foodics. Each customer has id, name, email, phone, and is_blacklisted. Supports pagination and search.",
        "tags": ["Foodics"],
        "parameters": [
          { "name": "page", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "default": 1 }, "description": "Page number." },
          { "name": "page_size", "in": "query", "required": false, "schema": { "type": "integer", "minimum": 1, "maximum": 50, "default": 25 }, "description": "Results per page (max 50)." },
          { "name": "search", "in": "query", "required": false, "schema": { "type": "string" }, "description": "Search by customer name, email, or phone." }
        ],
        "responses": {
          "200": {
            "description": "List of customers.",
            "content": {
              "application/json": {
                "schema": { "$ref": "#/components/schemas/FoodicsCustomersResponse" },
                "example": {
                  "success": true,
                  "data": {
                    "customers": [{ "id": "cust001", "name": "Ahmed Ali", "email": "ahmed@example.com", "phone": "+966501234567", "is_blacklisted": false }],
                    "pagination": { "page": 1, "total_pages": 1, "total_count": 1 }
                  },
                  "meta": { "request_id": "req_abc123", "timestamp": "2026-02-24T12:00:00.000Z", "environment": "sandbox" }
                }
              }
            }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": { "description": "Foodics not connected.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    },
    "/v1/foodics/customers/{id}": {
      "get": {
        "operationId": "getFoodicsCustomer",
        "summary": "Get customer",
        "description": "Retrieve details of a specific Foodics customer by their HID.",
        "tags": ["Foodics"],
        "parameters": [
          { "name": "id", "in": "path", "required": true, "description": "Foodics customer HID.", "schema": { "type": "string" } }
        ],
        "responses": {
          "200": {
            "description": "Customer detail.",
            "content": { "application/json": { "schema": { "$ref": "#/components/schemas/FoodicsCustomerResponse" } } }
          },
          "401": { "$ref": "#/components/responses/Unauthorized" },
          "422": { "description": "Foodics not connected.", "content": { "application/json": { "schema": { "$ref": "#/components/schemas/ErrorResponse" } } } }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "API key authentication. Pass your API key in the Authorization header as `Bearer <api_key>`. Keys use the format `jbr_test_<random>` for sandbox and `jbr_live_<random>` for production. Test keys always route to the ZATCA sandbox regardless of other settings. Get your API key from the Jibrid dashboard at https://www.jibrid.com/dashboard/settings."
      }
    },
    "responses": {
      "Unauthorized": {
        "description": "Authentication failed — missing, invalid, or disabled API key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "missing_key": {
                "summary": "No API key provided",
                "value": {
                  "success": false,
                  "error": {
                    "code": "MISSING_API_KEY",
                    "message": "Authorization header is required",
                    "message_ar": "مفتاح API مطلوب"
                  },
                  "meta": {
                    "request_id": "req_xyz789",
                    "timestamp": "2025-01-15T10:30:00.000Z",
                    "environment": "sandbox"
                  }
                }
              },
              "invalid_key": {
                "summary": "Invalid API key",
                "value": {
                  "success": false,
                  "error": {
                    "code": "INVALID_API_KEY",
                    "message": "API key is invalid or not found",
                    "message_ar": "مفتاح API غير صالح"
                  },
                  "meta": {
                    "request_id": "req_xyz789",
                    "timestamp": "2025-01-15T10:30:00.000Z",
                    "environment": "sandbox"
                  }
                }
              }
            }
          }
        }
      }
    },
    "schemas": {
      "ApiMeta": {
        "type": "object",
        "description": "Request metadata included in every API response.",
        "required": ["request_id", "timestamp", "environment"],
        "properties": {
          "request_id": {
            "type": "string",
            "description": "Unique request identifier for debugging and support. Format: req_<random>.",
            "example": "req_abc123def456"
          },
          "timestamp": {
            "type": "string",
            "format": "date-time",
            "description": "ISO 8601 timestamp of the response.",
            "example": "2025-01-15T14:30:00.000Z"
          },
          "environment": {
            "type": "string",
            "enum": ["sandbox", "production"],
            "description": "ZATCA environment this request was processed in. Test keys (jbr_test_*) always use sandbox."
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "description": "Standard error response envelope.",
        "required": ["success", "error", "meta"],
        "properties": {
          "success": {
            "type": "boolean",
            "const": false,
            "description": "Always false for error responses."
          },
          "error": {
            "type": "object",
            "required": ["code", "message", "message_ar"],
            "properties": {
              "code": {
                "type": "string",
                "description": "Machine-readable error code for programmatic handling.",
                "enum": [
                  "MISSING_API_KEY",
                  "INVALID_AUTH_FORMAT",
                  "INVALID_KEY_FORMAT",
                  "INVALID_API_KEY",
                  "KEY_DISABLED",
                  "MISSING_FIELD",
                  "INVALID_VAT_NUMBER",
                  "INVALID_INVOICE_TYPE",
                  "INVALID_DATE",
                  "INVALID_TIME",
                  "NOT_ONBOARDED",
                  "ONBOARDING_FAILED",
                  "INVOICE_SUBMISSION_FAILED",
                  "NOT_FOUND",
                  "LIST_FAILED",
                  "STATUS_FAILED",
                  "QOYOD_NOT_CONNECTED",
                  "QOYOD_AUTH_ERROR",
                  "QOYOD_VALIDATION_ERROR",
                  "QOYOD_NOT_FOUND",
                  "QOYOD_RATE_LIMIT",
                  "QOYOD_UNAVAILABLE",
                  "FOODICS_NOT_CONNECTED",
                  "FOODICS_REQUEST_FAILED"
                ]
              },
              "message": {
                "type": "string",
                "description": "Human-readable error message in English."
              },
              "message_ar": {
                "type": "string",
                "description": "Human-readable error message in Arabic (العربية)."
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ApiMeta"
          }
        }
      },
      "Address": {
        "type": "object",
        "description": "Saudi address following ZATCA requirements.",
        "required": ["street", "city", "district", "postal_code"],
        "properties": {
          "street": {
            "type": "string",
            "description": "Street name.",
            "example": "King Fahd Road"
          },
          "building_number": {
            "type": "string",
            "description": "Building number — must be exactly 4 digits if provided.",
            "pattern": "^\\d{4}$",
            "example": "2929"
          },
          "city": {
            "type": "string",
            "description": "City name.",
            "example": "Riyadh"
          },
          "district": {
            "type": "string",
            "description": "District or neighborhood name.",
            "example": "Al Olaya"
          },
          "postal_code": {
            "type": "string",
            "description": "5-digit Saudi postal code.",
            "pattern": "^\\d{5}$",
            "example": "12345"
          }
        }
      },
      "Seller": {
        "type": "object",
        "description": "Seller (supplier) information. VAT number must match the onboarded organization.",
        "required": ["vat_number", "name", "address"],
        "properties": {
          "vat_number": {
            "type": "string",
            "description": "15-digit Saudi VAT registration number. Must start and end with 3.",
            "pattern": "^3\\d{13}3$",
            "example": "399999999900003"
          },
          "name": {
            "type": "string",
            "description": "Legal name of the seller organization.",
            "example": "Acme Trading LLC"
          },
          "commercial_registration": {
            "type": "string",
            "description": "10-digit Commercial Registration Number (CRN) from the Ministry of Commerce. Optional for sandbox.",
            "pattern": "^\\d{10}$",
            "example": "1010123456"
          },
          "address": {
            "$ref": "#/components/schemas/Address"
          }
        }
      },
      "Buyer": {
        "type": "object",
        "description": "Buyer (customer) information. Required for standard (B2B) invoices.",
        "required": ["name"],
        "properties": {
          "vat_number": {
            "type": "string",
            "description": "15-digit Saudi VAT number of the buyer. Required for standard invoices.",
            "pattern": "^3\\d{13}3$",
            "example": "399999999800003"
          },
          "name": {
            "type": "string",
            "description": "Legal name of the buyer organization.",
            "example": "Buyer Company Ltd"
          },
          "id_type": {
            "type": "string",
            "description": "Buyer identification type.",
            "enum": ["TIN", "CRN", "MOM", "MLS", "SAG", "NAT", "GCC", "IQA", "PAS", "OTH"],
            "example": "TIN"
          },
          "id_value": {
            "type": "string",
            "description": "Buyer identification value corresponding to id_type.",
            "example": "399999999800003"
          },
          "address": {
            "$ref": "#/components/schemas/Address"
          }
        }
      },
      "LineItem": {
        "type": "object",
        "description": "A single item/line on the invoice. VAT amount and line total are calculated server-side.",
        "required": ["name", "quantity", "unit_price", "vat_rate"],
        "properties": {
          "name": {
            "type": "string",
            "description": "Name or description of the item/service.",
            "example": "Web Development Service"
          },
          "quantity": {
            "type": "number",
            "description": "Quantity of items. Must be greater than 0.",
            "minimum": 0.01,
            "example": 1
          },
          "unit_price": {
            "type": "number",
            "description": "Price per unit in SAR (before VAT).",
            "minimum": 0,
            "example": 1000
          },
          "vat_rate": {
            "type": "number",
            "description": "VAT rate as a decimal. Use 0.15 for standard 15% VAT, 0 for zero-rated or exempt items.",
            "enum": [0.15, 0.05, 0],
            "example": 0.15
          }
        }
      },
      "ValidationMessage": {
        "type": "object",
        "description": "A validation message from ZATCA (error or warning).",
        "properties": {
          "type": {
            "type": "string",
            "description": "Message severity level.",
            "enum": ["ERROR", "WARNING", "INFO"]
          },
          "code": {
            "type": "string",
            "description": "ZATCA business rule code (e.g., BR-KSA-F-13).",
            "example": "BR-KSA-F-13"
          },
          "message": {
            "type": "string",
            "description": "Human-readable validation message from ZATCA.",
            "example": "Please recheck Other Seller/Buyer ID"
          }
        }
      },
      "OnboardRequest": {
        "type": "object",
        "description": "Request body for ZATCA onboarding.",
        "required": ["org_name", "vat_number", "otp"],
        "properties": {
          "org_name": {
            "type": "string",
            "description": "Legal name of the organization being onboarded.",
            "example": "Acme Trading LLC"
          },
          "vat_number": {
            "type": "string",
            "description": "15-digit Saudi VAT registration number. Must start and end with 3.",
            "pattern": "^3\\d{13}3$",
            "example": "399999999900003"
          },
          "otp": {
            "type": "string",
            "description": "One-Time Password from the ZATCA FATOORA portal. Use '123456' for sandbox testing.",
            "example": "123456"
          },
          "org_unit": {
            "type": "string",
            "description": "Branch or organizational unit name. Defaults to 'Main Branch'.",
            "default": "Main Branch",
            "example": "Riyadh Branch"
          },
          "city": {
            "type": "string",
            "description": "City where the EGS device is located. Defaults to 'Riyadh'.",
            "default": "Riyadh",
            "example": "Riyadh"
          },
          "common_name": {
            "type": "string",
            "description": "Certificate common name. Auto-generated if not provided.",
            "example": "TST-886431145-399999999900003"
          }
        }
      },
      "OnboardResponse": {
        "type": "object",
        "description": "Successful onboarding response.",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": {
            "type": "boolean",
            "const": true
          },
          "data": {
            "type": "object",
            "required": ["onboarding_id", "status", "vat_number", "egs_serial", "environment", "duration_ms"],
            "properties": {
              "onboarding_id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique identifier for this onboarding event."
              },
              "status": {
                "type": "string",
                "enum": ["active"],
                "description": "Onboarding status. 'active' means credentials are stored and ready."
              },
              "vat_number": {
                "type": "string",
                "description": "VAT number that was registered."
              },
              "egs_serial": {
                "type": "string",
                "description": "Unique EGS (Electronic Generation System) device serial number assigned to this connection.",
                "example": "1-Jibrid|2-1.0|3-f47ac10b-58cc-4372-a567-0e02b2c3d479"
              },
              "environment": {
                "type": "string",
                "enum": ["sandbox", "production"],
                "description": "ZATCA environment used for onboarding."
              },
              "duration_ms": {
                "type": "integer",
                "description": "Time taken for the full onboarding flow in milliseconds.",
                "example": 8432
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ApiMeta"
          }
        }
      },
      "InvoiceRequest": {
        "type": "object",
        "description": "Request body for submitting an invoice to ZATCA.",
        "required": ["invoice_type", "invoice_number", "issue_date", "issue_time", "seller", "items"],
        "properties": {
          "invoice_type": {
            "type": "string",
            "enum": ["simplified", "standard"],
            "description": "Type of invoice. 'simplified' for B2C (reported to ZATCA). 'standard' for B2B (cleared by ZATCA — requires buyer details)."
          },
          "invoice_number": {
            "type": "string",
            "description": "Your internal invoice number. Must be unique per organization.",
            "example": "INV-2025-001"
          },
          "issue_date": {
            "type": "string",
            "format": "date",
            "description": "Invoice issue date in YYYY-MM-DD format.",
            "example": "2025-01-15"
          },
          "issue_time": {
            "type": "string",
            "description": "Invoice issue time in HH:MM:SS format (24-hour).",
            "pattern": "^\\d{2}:\\d{2}:\\d{2}$",
            "example": "14:30:00"
          },
          "supply_date": {
            "type": "string",
            "format": "date",
            "description": "Date when goods/services were supplied. Defaults to issue_date if not provided.",
            "example": "2025-01-15"
          },
          "seller": {
            "$ref": "#/components/schemas/Seller"
          },
          "buyer": {
            "$ref": "#/components/schemas/Buyer",
            "description": "Buyer details. Required when invoice_type is 'standard'."
          },
          "items": {
            "type": "array",
            "description": "Invoice line items. At least one item is required.",
            "minItems": 1,
            "items": {
              "$ref": "#/components/schemas/LineItem"
            }
          },
          "payment_means": {
            "type": "string",
            "description": "UNCL 4461 payment means code. Common values: '10' (cash), '30' (credit transfer), '42' (bank account), '48' (bank card).",
            "default": "10",
            "example": "10"
          },
          "previous_invoice_hash": {
            "type": "string",
            "description": "Hash of the previous invoice in the chain. Used for invoice chaining (optional).",
            "example": "NWZlY2ViNjZmZmM4NmYzOGQ5NTI3ODZjNmQ2OTZjNzljMmRiYmVjZjc..."
          },
          "note": {
            "type": "string",
            "description": "Free-text note to include on the invoice.",
            "example": "Payment due within 30 days"
          }
        }
      },
      "InvoiceResponse": {
        "type": "object",
        "description": "Successful invoice submission response.",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": {
            "type": "boolean",
            "const": true
          },
          "data": {
            "type": "object",
            "required": ["invoice_id", "uuid", "invoice_number", "status", "invoice_hash", "qr_code", "validation_results", "totals"],
            "properties": {
              "invoice_id": {
                "type": "string",
                "format": "uuid",
                "description": "Unique invoice ID in the Jibrid system. Use this to retrieve the invoice later."
              },
              "uuid": {
                "type": "string",
                "format": "uuid",
                "description": "ZATCA-assigned UUID for this invoice."
              },
              "invoice_number": {
                "type": "string",
                "description": "Your internal invoice number (echoed back)."
              },
              "status": {
                "type": "string",
                "enum": ["REPORTED", "CLEARED", "NOT_REPORTED", "NOT_CLEARED", "ERROR"],
                "description": "Overall ZATCA submission status. REPORTED = simplified invoice accepted. CLEARED = standard invoice approved."
              },
              "reporting_status": {
                "type": ["string", "null"],
                "description": "ZATCA reporting status for simplified invoices.",
                "enum": ["REPORTED", "NOT_REPORTED", null]
              },
              "clearance_status": {
                "type": ["string", "null"],
                "description": "ZATCA clearance status for standard invoices.",
                "enum": ["CLEARED", "NOT_CLEARED", null]
              },
              "invoice_hash": {
                "type": "string",
                "description": "SHA-256 hash of the signed invoice XML (base64-encoded)."
              },
              "qr_code": {
                "type": "string",
                "description": "ZATCA-compliant QR code data (base64 TLV-encoded). Encode as a QR image for printing."
              },
              "validation_results": {
                "type": "object",
                "description": "ZATCA validation results.",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": ["PASS", "WARNING", "ERROR"],
                    "description": "Overall validation status."
                  },
                  "errors": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/ValidationMessage"
                    },
                    "description": "Validation errors (invoice was rejected)."
                  },
                  "warnings": {
                    "type": "array",
                    "items": {
                      "$ref": "#/components/schemas/ValidationMessage"
                    },
                    "description": "Validation warnings (invoice accepted but with issues)."
                  }
                }
              },
              "totals": {
                "type": "object",
                "description": "Calculated invoice totals.",
                "properties": {
                  "subtotal": {
                    "type": "number",
                    "description": "Total before VAT in SAR."
                  },
                  "vat_total": {
                    "type": "number",
                    "description": "Total VAT amount in SAR."
                  },
                  "total": {
                    "type": "number",
                    "description": "Grand total including VAT in SAR."
                  },
                  "currency": {
                    "type": "string",
                    "const": "SAR",
                    "description": "Currency code (always SAR)."
                  }
                }
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ApiMeta"
          }
        }
      },
      "InvoiceListResponse": {
        "type": "object",
        "description": "Paginated list of invoices.",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": {
            "type": "boolean",
            "const": true
          },
          "data": {
            "type": "object",
            "properties": {
              "invoices": {
                "type": "array",
                "items": {
                  "type": "object",
                  "description": "Invoice summary.",
                  "properties": {
                    "id": { "type": "string", "format": "uuid", "description": "Invoice ID." },
                    "uuid": { "type": "string", "format": "uuid", "description": "ZATCA UUID." },
                    "invoice_number": { "type": "string", "description": "Your internal invoice number." },
                    "invoice_type": { "type": "string", "enum": ["simplified", "standard"], "description": "Invoice type." },
                    "subtotal": { "type": "number", "description": "Subtotal in SAR." },
                    "vat_total": { "type": "number", "description": "VAT total in SAR." },
                    "total": { "type": "number", "description": "Grand total in SAR." },
                    "currency": { "type": "string", "description": "Currency code." },
                    "zatca_status": { "type": "string", "description": "ZATCA submission status." },
                    "reporting_status": { "type": ["string", "null"], "description": "Reporting status." },
                    "clearance_status": { "type": ["string", "null"], "description": "Clearance status." },
                    "validation_status": { "type": ["string", "null"], "description": "Validation status." },
                    "invoice_hash": { "type": "string", "description": "Invoice hash." },
                    "qr_code": { "type": "string", "description": "QR code data." },
                    "issue_date": { "type": "string", "format": "date", "description": "Issue date." },
                    "issue_time": { "type": "string", "description": "Issue time." },
                    "created_at": { "type": "string", "format": "date-time", "description": "Creation timestamp." }
                  }
                }
              },
              "pagination": {
                "type": "object",
                "description": "Pagination metadata.",
                "properties": {
                  "page": { "type": "integer", "description": "Current page number." },
                  "limit": { "type": "integer", "description": "Items per page." },
                  "total": { "type": "integer", "description": "Total number of invoices." },
                  "total_pages": { "type": "integer", "description": "Total number of pages." }
                }
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ApiMeta"
          }
        }
      },
      "InvoiceDetailResponse": {
        "type": "object",
        "description": "Full invoice detail response.",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": {
            "type": "boolean",
            "const": true
          },
          "data": {
            "type": "object",
            "properties": {
              "invoice": {
                "type": "object",
                "description": "Complete invoice record with ZATCA response data.",
                "properties": {
                  "id": { "type": "string", "format": "uuid", "description": "Invoice ID." },
                  "uuid": { "type": "string", "format": "uuid", "description": "ZATCA UUID." },
                  "invoice_number": { "type": "string", "description": "Your internal invoice number." },
                  "invoice_type": { "type": "string", "enum": ["simplified", "standard"], "description": "Invoice type." },
                  "invoice_counter": { "type": "integer", "description": "Sequential invoice counter for this organization." },
                  "subtotal": { "type": "number", "description": "Subtotal in SAR." },
                  "vat_total": { "type": "number", "description": "VAT total in SAR." },
                  "total": { "type": "number", "description": "Grand total in SAR." },
                  "currency": { "type": "string", "description": "Currency code." },
                  "zatca_status": { "type": "string", "description": "ZATCA submission status." },
                  "reporting_status": { "type": ["string", "null"], "description": "Reporting status for simplified invoices." },
                  "clearance_status": { "type": ["string", "null"], "description": "Clearance status for standard invoices." },
                  "validation_status": { "type": ["string", "null"], "description": "ZATCA validation result." },
                  "validation_errors": { "type": ["array", "null"], "items": { "$ref": "#/components/schemas/ValidationMessage" }, "description": "Validation errors from ZATCA." },
                  "validation_warnings": { "type": ["array", "null"], "items": { "$ref": "#/components/schemas/ValidationMessage" }, "description": "Validation warnings from ZATCA." },
                  "invoice_hash": { "type": "string", "description": "SHA-256 hash of the signed XML." },
                  "qr_code": { "type": "string", "description": "QR code data (base64 TLV)." },
                  "issue_date": { "type": "string", "format": "date", "description": "Issue date." },
                  "issue_time": { "type": "string", "description": "Issue time." },
                  "request_payload": { "type": "object", "description": "Original request body that was submitted." },
                  "created_at": { "type": "string", "format": "date-time", "description": "Record creation timestamp." }
                }
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ApiMeta"
          }
        }
      },
      "StatusResponse": {
        "type": "object",
        "description": "ZATCA connection status and statistics.",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": {
            "type": "boolean",
            "const": true
          },
          "data": {
            "type": "object",
            "properties": {
              "onboarding": {
                "type": "object",
                "description": "ZATCA onboarding status.",
                "properties": {
                  "status": {
                    "type": "string",
                    "enum": ["active", "not_onboarded", "expired"],
                    "description": "Current onboarding status."
                  },
                  "vat_number": {
                    "type": "string",
                    "description": "Registered VAT number (only when status is 'active')."
                  },
                  "egs_serial": {
                    "type": "string",
                    "description": "EGS device serial number."
                  },
                  "environment": {
                    "type": "string",
                    "enum": ["sandbox", "production"],
                    "description": "ZATCA environment."
                  },
                  "onboarded_at": {
                    "type": ["string", "null"],
                    "format": "date-time",
                    "description": "When the organization was onboarded."
                  },
                  "expires_at": {
                    "type": ["string", "null"],
                    "format": "date-time",
                    "description": "Certificate expiration date (null if not applicable)."
                  }
                }
              },
              "stats": {
                "type": "object",
                "description": "Invoice submission statistics.",
                "properties": {
                  "total_invoices": {
                    "type": "integer",
                    "description": "Total number of invoices ever submitted."
                  },
                  "last_30_days": {
                    "type": "integer",
                    "description": "Number of invoices submitted in the last 30 days."
                  },
                  "errors_last_30_days": {
                    "type": "integer",
                    "description": "Number of failed invoice submissions in the last 30 days."
                  }
                }
              },
              "plan": {
                "type": "string",
                "description": "Current API plan.",
                "example": "free"
              },
              "rate_limit_per_minute": {
                "type": "integer",
                "description": "Maximum API requests allowed per minute.",
                "example": 60
              }
            }
          },
          "meta": {
            "$ref": "#/components/schemas/ApiMeta"
          }
        }
      },
      "QoyodStatusResponse": {
        "type": "object",
        "description": "Qoyod connection status.",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "connected": { "type": "boolean", "description": "Whether Qoyod is connected." },
              "connector": { "type": "string", "const": "qoyod" }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "QoyodAccount": {
        "type": "object",
        "description": "A Qoyod chart of accounts entry.",
        "properties": {
          "id": { "type": "integer", "description": "Account ID." },
          "name": { "type": "string", "description": "Account name (English)." },
          "name_ar": { "type": "string", "description": "Account name (Arabic)." },
          "code": { "type": "string", "description": "Account code." },
          "account_type": { "type": "string", "enum": ["asset", "liability", "equity", "revenue", "expense"], "description": "Account type." },
          "parent_id": { "type": ["integer", "null"], "description": "Parent account ID." },
          "is_active": { "type": "boolean", "description": "Whether the account is active." }
        }
      },
      "QoyodAccountsResponse": {
        "type": "object",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "accounts": { "type": "array", "items": { "$ref": "#/components/schemas/QoyodAccount" } }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "QoyodCustomer": {
        "type": "object",
        "description": "A Qoyod customer.",
        "properties": {
          "id": { "type": "integer", "description": "Customer ID." },
          "name": { "type": "string", "description": "Customer name." },
          "email": { "type": "string", "description": "Email address." },
          "phone": { "type": "string", "description": "Phone number." },
          "vat_number": { "type": "string", "description": "VAT registration number." },
          "address": { "type": "string", "description": "Street address." },
          "city": { "type": "string", "description": "City." },
          "country": { "type": "string", "description": "Country code." }
        }
      },
      "QoyodCustomersResponse": {
        "type": "object",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "customers": { "type": "array", "items": { "$ref": "#/components/schemas/QoyodCustomer" } }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "QoyodCustomerResponse": {
        "type": "object",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "customer": { "$ref": "#/components/schemas/QoyodCustomer" }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "QoyodCreateCustomerRequest": {
        "type": "object",
        "description": "Request body for creating a Qoyod customer.",
        "required": ["name"],
        "properties": {
          "name": { "type": "string", "description": "Customer name." },
          "email": { "type": "string", "description": "Email address." },
          "phone": { "type": "string", "description": "Phone number." },
          "vat_number": { "type": "string", "description": "VAT registration number." },
          "address": { "type": "string", "description": "Street address." },
          "city": { "type": "string", "description": "City." },
          "country": { "type": "string", "description": "ISO country code (e.g. SA)." }
        }
      },
      "QoyodLineItem": {
        "type": "object",
        "description": "A line item on a Qoyod invoice.",
        "required": ["description", "quantity", "unit_price"],
        "properties": {
          "product_id": { "type": "integer", "description": "Qoyod product ID (optional)." },
          "description": { "type": "string", "description": "Item description." },
          "quantity": { "type": "number", "description": "Quantity." },
          "unit_price": { "type": "number", "description": "Unit price." },
          "tax_rate": { "type": "number", "description": "Tax rate percentage (e.g. 15 for 15%)." },
          "tax_amount": { "type": "number", "description": "Calculated tax amount (response only)." },
          "total": { "type": "number", "description": "Line total including tax (response only)." }
        }
      },
      "QoyodInvoice": {
        "type": "object",
        "description": "A Qoyod invoice.",
        "properties": {
          "id": { "type": "integer", "description": "Invoice ID." },
          "reference": { "type": "string", "description": "Invoice reference number." },
          "customer_id": { "type": "integer", "description": "Customer ID." },
          "date": { "type": "string", "format": "date", "description": "Invoice date." },
          "due_date": { "type": "string", "format": "date", "description": "Due date." },
          "status": { "type": "string", "enum": ["draft", "sent", "paid", "overdue", "void"], "description": "Invoice status." },
          "subtotal": { "type": "number", "description": "Subtotal before tax." },
          "tax_total": { "type": "number", "description": "Total tax." },
          "total": { "type": "number", "description": "Grand total." },
          "notes": { "type": "string", "description": "Invoice notes." },
          "line_items": { "type": "array", "items": { "$ref": "#/components/schemas/QoyodLineItem" } }
        }
      },
      "QoyodInvoicesResponse": {
        "type": "object",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "invoices": { "type": "array", "items": { "$ref": "#/components/schemas/QoyodInvoice" } }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "QoyodInvoiceResponse": {
        "type": "object",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "invoice": { "$ref": "#/components/schemas/QoyodInvoice" }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "QoyodCreateInvoiceRequest": {
        "type": "object",
        "description": "Request body for creating a Qoyod invoice.",
        "required": ["date", "line_items"],
        "properties": {
          "customer_id": { "type": "integer", "description": "Existing Qoyod customer ID. Required if customer_name is not provided." },
          "customer_name": { "type": "string", "description": "Inline customer name. Required if customer_id is not provided." },
          "customer_vat": { "type": "string", "description": "Customer VAT number (only with customer_name)." },
          "date": { "type": "string", "format": "date", "description": "Invoice date (YYYY-MM-DD)." },
          "due_date": { "type": "string", "format": "date", "description": "Payment due date (YYYY-MM-DD)." },
          "reference": { "type": "string", "description": "Invoice reference number." },
          "notes": { "type": "string", "description": "Invoice notes." },
          "line_items": {
            "type": "array",
            "minItems": 1,
            "items": {
              "type": "object",
              "required": ["description", "quantity", "unit_price"],
              "properties": {
                "description": { "type": "string" },
                "quantity": { "type": "number" },
                "unit_price": { "type": "number" },
                "tax_rate": { "type": "number", "description": "Tax rate percentage (e.g. 15)." },
                "product_id": { "type": "integer", "description": "Qoyod product ID." }
              }
            }
          }
        }
      },
      "QoyodProduct": {
        "type": "object",
        "description": "A Qoyod product.",
        "properties": {
          "id": { "type": "integer", "description": "Product ID." },
          "name": { "type": "string", "description": "Product name (English)." },
          "name_ar": { "type": "string", "description": "Product name (Arabic)." },
          "sku": { "type": "string", "description": "SKU code." },
          "price": { "type": "number", "description": "Unit price." },
          "tax_rate": { "type": "number", "description": "Tax rate percentage." },
          "is_active": { "type": "boolean", "description": "Whether the product is active." }
        }
      },
      "QoyodProductsResponse": {
        "type": "object",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "products": { "type": "array", "items": { "$ref": "#/components/schemas/QoyodProduct" } }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "FoodicsPagination": {
        "type": "object",
        "description": "Pagination metadata for Foodics list responses.",
        "properties": {
          "page": { "type": "integer", "description": "Current page number." },
          "total_pages": { "type": "integer", "description": "Total number of pages." },
          "total_count": { "type": "integer", "description": "Total number of records." }
        }
      },
      "FoodicsStatusResponse": {
        "type": "object",
        "description": "Foodics connection status.",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "connection": {
                "type": "object",
                "properties": {
                  "status": { "type": "string", "enum": ["connected", "not_connected"] },
                  "connector": { "type": "string", "const": "foodics" }
                }
              },
              "plan": { "type": "string" },
              "rate_limit_per_minute": { "type": "integer" }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "FoodicsBranch": {
        "type": "object",
        "description": "A Foodics branch (store location).",
        "properties": {
          "id": { "type": "string", "description": "Foodics HID." },
          "name": { "type": "string", "description": "Branch name (English)." },
          "name_ar": { "type": "string", "description": "Branch name (Arabic)." },
          "reference": { "type": ["string", "null"], "description": "Reference code." },
          "phone": { "type": ["string", "null"], "description": "Phone number." },
          "address": { "type": ["string", "null"], "description": "Street address." },
          "city": { "type": ["string", "null"], "description": "City." },
          "is_active": { "type": "boolean", "description": "Whether the branch is active." }
        }
      },
      "FoodicsBranchesResponse": {
        "type": "object",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "branches": { "type": "array", "items": { "$ref": "#/components/schemas/FoodicsBranch" } },
              "pagination": { "$ref": "#/components/schemas/FoodicsPagination" }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "FoodicsBranchResponse": {
        "type": "object",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "branch": { "$ref": "#/components/schemas/FoodicsBranch" }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "FoodicsProduct": {
        "type": "object",
        "description": "A Foodics product (menu item).",
        "properties": {
          "id": { "type": "string", "description": "Foodics HID." },
          "name": { "type": "string", "description": "Product name (English)." },
          "name_ar": { "type": "string", "description": "Product name (Arabic)." },
          "sku": { "type": ["string", "null"], "description": "SKU code." },
          "price": { "type": "number", "description": "Price in SAR." },
          "category_id": { "type": ["string", "null"], "description": "Category HID." },
          "is_active": { "type": "boolean", "description": "Whether the product is active." }
        }
      },
      "FoodicsProductsResponse": {
        "type": "object",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "products": { "type": "array", "items": { "$ref": "#/components/schemas/FoodicsProduct" } },
              "pagination": { "$ref": "#/components/schemas/FoodicsPagination" }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "FoodicsProductResponse": {
        "type": "object",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "product": { "$ref": "#/components/schemas/FoodicsProduct" }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "FoodicsCategory": {
        "type": "object",
        "description": "A Foodics product category.",
        "properties": {
          "id": { "type": "string", "description": "Foodics HID." },
          "name": { "type": "string", "description": "Category name (English)." },
          "name_ar": { "type": "string", "description": "Category name (Arabic)." },
          "parent_id": { "type": ["string", "null"], "description": "Parent category HID." },
          "is_active": { "type": "boolean", "description": "Whether the category is active." }
        }
      },
      "FoodicsCategoriesResponse": {
        "type": "object",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "categories": { "type": "array", "items": { "$ref": "#/components/schemas/FoodicsCategory" } },
              "pagination": { "$ref": "#/components/schemas/FoodicsPagination" }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "FoodicsOrderLineItem": {
        "type": "object",
        "description": "A line item within a Foodics order.",
        "properties": {
          "product_id": { "type": "string", "description": "Product HID." },
          "name": { "type": "string", "description": "Display name." },
          "quantity": { "type": "number", "description": "Quantity ordered." },
          "unit_price": { "type": "number", "description": "Unit price in SAR." },
          "discount": { "type": "number", "description": "Discount on this line in SAR." },
          "total": { "type": "number", "description": "Line total in SAR." },
          "notes": { "type": ["string", "null"], "description": "Special instructions." }
        }
      },
      "FoodicsOrderPayment": {
        "type": "object",
        "description": "A payment record on a Foodics order.",
        "properties": {
          "method": { "type": "string", "description": "Payment method name." },
          "amount": { "type": "number", "description": "Payment amount in SAR." },
          "tip": { "type": "number", "description": "Tip amount in SAR." }
        }
      },
      "FoodicsOrderTax": {
        "type": "object",
        "description": "Tax applied to a Foodics order.",
        "properties": {
          "name": { "type": "string", "description": "Tax name." },
          "rate": { "type": "number", "description": "Tax rate percentage." },
          "amount": { "type": "number", "description": "Tax amount in SAR." }
        }
      },
      "FoodicsOrder": {
        "type": "object",
        "description": "A Foodics order.",
        "properties": {
          "id": { "type": "string", "description": "Foodics HID." },
          "number": { "type": "integer", "description": "Order number." },
          "branch_id": { "type": "string", "description": "Branch HID." },
          "customer_id": { "type": ["string", "null"], "description": "Customer HID (null = walk-in)." },
          "type": { "type": "string", "enum": ["dine_in", "pickup", "delivery", "drive_through"], "description": "Order type." },
          "status": { "type": "string", "enum": ["closed", "void", "returned"], "description": "Order status." },
          "subtotal": { "type": "number", "description": "Subtotal before tax/discount in SAR." },
          "discount": { "type": "number", "description": "Discount amount in SAR." },
          "total": { "type": "number", "description": "Total after tax/discount in SAR." },
          "taxes": { "type": "array", "items": { "$ref": "#/components/schemas/FoodicsOrderTax" } },
          "line_items": { "type": "array", "items": { "$ref": "#/components/schemas/FoodicsOrderLineItem" } },
          "payments": { "type": "array", "items": { "$ref": "#/components/schemas/FoodicsOrderPayment" } },
          "business_date": { "type": "string", "format": "date", "description": "Business day date." },
          "created_at": { "type": "string", "format": "date-time", "description": "Creation timestamp." }
        }
      },
      "FoodicsOrdersResponse": {
        "type": "object",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "orders": { "type": "array", "items": { "$ref": "#/components/schemas/FoodicsOrder" } },
              "pagination": { "$ref": "#/components/schemas/FoodicsPagination" }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "FoodicsOrderResponse": {
        "type": "object",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "order": { "$ref": "#/components/schemas/FoodicsOrder" }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "FoodicsCustomer": {
        "type": "object",
        "description": "A Foodics customer.",
        "properties": {
          "id": { "type": "string", "description": "Foodics HID." },
          "name": { "type": "string", "description": "Customer name." },
          "email": { "type": ["string", "null"], "description": "Email address." },
          "phone": { "type": ["string", "null"], "description": "Phone number." },
          "is_blacklisted": { "type": "boolean", "description": "Whether the customer is blacklisted." }
        }
      },
      "FoodicsCustomersResponse": {
        "type": "object",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "customers": { "type": "array", "items": { "$ref": "#/components/schemas/FoodicsCustomer" } },
              "pagination": { "$ref": "#/components/schemas/FoodicsPagination" }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      },
      "FoodicsCustomerResponse": {
        "type": "object",
        "required": ["success", "data", "meta"],
        "properties": {
          "success": { "type": "boolean", "const": true },
          "data": {
            "type": "object",
            "properties": {
              "customer": { "$ref": "#/components/schemas/FoodicsCustomer" }
            }
          },
          "meta": { "$ref": "#/components/schemas/ApiMeta" }
        }
      }
    }
  }
}
