{
  "openapi": "3.1.0",
  "info": {
    "title": "OpenQloud Customer API",
    "version": "1.0.0",
    "description": "Contracting and restaurant provisioning, independently of POS, marketplace, middleware or other software capabilities. A customer account must be explicitly enabled and ready for billing before provisioning; a server token alone grants no commercial authority. This contract does not grant restaurant data access or subscribe software to events."
  },
  "servers": [
    {
      "url": "https://api.openqloud.com"
    }
  ],
  "security": [
    {
      "ServerToken": []
    }
  ],
  "tags": [
    {
      "name": "Account"
    }
  ],
  "paths": {
    "/v1/customer-accounts/{customerAccountOqid}/tariff/history": {
      "get": {
        "operationId": "listCustomerTariffHistory",
        "tags": [
          "Account"
        ],
        "summary": "Read customer financial terms history",
        "description": "Explicit current financial membership and active account required. Ascending revision cursor pagination. Staff identities and restaurant operational data are excluded. History is an audit trail, not a consumption ledger, invoice, effective-tariff selection or payment. Historical terms created before revision tracking may have no history entry.",
        "parameters": [
          {
            "name": "customerAccountOqid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 19
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized revision page",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerTariffHistoryResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid pagination",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "UNAUTHORIZED",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "BILLING_ACCESS_DENIED",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/customer-accounts/{customerAccountOqid}/tariff": {
      "get": {
        "operationId": "getCustomerTariff",
        "tags": [
          "Account"
        ],
        "summary": "Read the customer account's financial terms",
        "description": "Requires explicit financial membership and an active customer account. Software category and provisioning authority do not grant financial access. Returns the latest registered terms, including future-dated, expired or retired terms; it does not select a tariff effective at the current date or replay historical revisions. Consumers must not treat this snapshot as authorization to calculate charges. Missing terms return null, not a free plan. Pending terms do not enable provisioning. Decimal amounts are strings in the indicated currency per unit; this is not a consumption estimate, invoice or payment operation. No restaurant data or event subscriptions are returned or granted.",
        "parameters": [
          {
            "name": "customerAccountOqid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Financial terms, or null when no terms are configured",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerTariffResponse"
                }
              }
            }
          },
          "401": {
            "description": "UNAUTHORIZED",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "BILLING_ACCESS_DENIED; foreign, unknown and suspended accounts are indistinguishable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/customer-accounts/{customerAccountOqid}/billing-assignments": {
      "get": {
        "operationId": "listCustomerBillingAssignments",
        "tags": [
          "Account"
        ],
        "summary": "List restaurants financially assigned to a customer account",
        "description": "Requires an active customer account and explicit financial membership (canManageBilling). Provisioning authority or middleware software credentials alone are insufficient. Returns identifiers only, not operational data, prices, invoices or a consumption estimate. Financial responsibility grants no restaurant capabilities or event subscription. Cursor is the last returned sellingPointId as a decimal string.",
        "parameters": [
          {
            "name": "customerAccountOqid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 16
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Active financial assignments ordered by restaurant identifier",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BillingAssignmentsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid limit or decimal cursor",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "UNAUTHORIZED",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "BILLING_ACCESS_DENIED; foreign, unknown, suspended accounts and missing financial authority are indistinguishable",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/customer-accounts": {
      "get": {
        "operationId": "listCustomerAccounts",
        "tags": [
          "Account"
        ],
        "summary": "Customer accounts explicitly assigned to the calling application",
        "description": "Uses a developer account server credential. No middleware registration is required. Returns only explicit customer memberships, independently of software category.",
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 100,
              "default": 50
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string",
              "maxLength": 256
            }
          }
        ],
        "responses": {
          "200": {
            "description": "Authorized customer accounts, ordered by identifier",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerAccountsResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid pagination",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "UNAUTHORIZED",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    },
    "/v1/customer-accounts/{customerAccountOqid}/restaurants": {
      "post": {
        "operationId": "provisionCustomerRestaurant",
        "tags": [
          "Account"
        ],
        "summary": "Provision a restaurant under an enabled customer account",
        "description": "Requires explicit provisioning membership and a ready billing account. Does not create or assign middleware software, grant operational access, or subscribe any recipient to events. Repeating clientReference with the same payload returns the same restaurant.",
        "parameters": [
          {
            "name": "customerAccountOqid",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CustomerProvisioningRequest"
              }
            }
          }
        },
        "responses": {
          "200": {
            "description": "Created or idempotently recovered",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CustomerProvisioningResponse"
                }
              }
            }
          },
          "400": {
            "description": "Invalid input",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "401": {
            "description": "UNAUTHORIZED",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "403": {
            "description": "PROVISIONING_NOT_AUTHORIZED",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          },
          "409": {
            "description": "PROVISIONING_REFERENCE_CONFLICT",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ErrorResponse"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ServerToken": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-server-access-token"
      }
    },
    "schemas": {
      "CustomerTariffHistoryResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "const": true
          },
          "data": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "items",
              "nextCursor"
            ],
            "properties": {
              "nextCursor": {
                "type": [
                  "string",
                  "null"
                ]
              },
              "items": {
                "type": "array",
                "maxItems": 100,
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "revision",
                    "occurredAt",
                    "previousTerms",
                    "replacementTerms"
                  ],
                  "properties": {
                    "revision": {
                      "type": "string",
                      "pattern": "^[1-9][0-9]*$"
                    },
                    "occurredAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "previousTerms": {
                      "oneOf": [
                        {
                          "type": "null"
                        },
                        {
                          "$ref": "#/components/schemas/CustomerTariff"
                        }
                      ]
                    },
                    "replacementTerms": {
                      "$ref": "#/components/schemas/CustomerTariff"
                    }
                  }
                }
              }
            }
          }
        }
      },
      "CustomerTariffResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "const": true
          },
          "data": {
            "oneOf": [
              {
                "type": "null"
              },
              {
                "$ref": "#/components/schemas/CustomerTariff"
              }
            ]
          }
        }
      },
      "CustomerTariff": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "currency",
          "status",
          "perConnection",
          "perSellingPoint",
          "perBrand",
          "perOrder",
          "monthlyMinimum",
          "validFrom",
          "validUntil"
        ],
        "properties": {
          "currency": {
            "type": "string",
            "pattern": "^[A-Z]{3}$"
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "active",
              "retired"
            ]
          },
          "perConnection": {
            "$ref": "#/components/schemas/DecimalAmount"
          },
          "perSellingPoint": {
            "$ref": "#/components/schemas/DecimalAmount"
          },
          "perBrand": {
            "$ref": "#/components/schemas/DecimalAmount"
          },
          "perOrder": {
            "$ref": "#/components/schemas/DecimalAmount"
          },
          "monthlyMinimum": {
            "$ref": "#/components/schemas/DecimalAmount"
          },
          "validFrom": {
            "type": "string",
            "format": "date"
          },
          "validUntil": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          }
        }
      },
      "DecimalAmount": {
        "type": "string",
        "pattern": "^[0-9]+\\.[0-9]{4}$",
        "description": "Non-negative monetary amount in the tariff currency, with four decimal places. Preserve decimal arithmetic when calculating charges."
      },
      "BillingAssignmentsResponse": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "const": true
          },
          "data": {
            "type": "object",
            "additionalProperties": false,
            "required": [
              "items",
              "nextCursor"
            ],
            "properties": {
              "items": {
                "type": "array",
                "maxItems": 100,
                "items": {
                  "type": "object",
                  "additionalProperties": false,
                  "required": [
                    "sellingPointId"
                  ],
                  "properties": {
                    "sellingPointId": {
                      "type": "integer",
                      "minimum": 1,
                      "maximum": 9007199254740991
                    }
                  }
                }
              },
              "nextCursor": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        }
      },
      "CustomerAccountsResponse": {
        "type": "object",
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "const": true
          },
          "data": {
            "type": "object",
            "required": [
              "items",
              "nextCursor"
            ],
            "properties": {
              "items": {
                "type": "array",
                "items": {
                  "type": "object",
                  "required": [
                    "oqid",
                    "name",
                    "status",
                    "canProvision",
                    "canManageBilling"
                  ],
                  "properties": {
                    "oqid": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "status": {
                      "type": "string"
                    },
                    "canProvision": {
                      "type": "boolean"
                    },
                    "canManageBilling": {
                      "type": "boolean"
                    }
                  }
                }
              },
              "nextCursor": {
                "type": [
                  "string",
                  "null"
                ]
              }
            }
          }
        }
      },
      "CustomerProvisioningResponse": {
        "type": "object",
        "required": [
          "success",
          "data"
        ],
        "properties": {
          "success": {
            "const": true
          },
          "data": {
            "type": "object",
            "required": [
              "sellingPointId",
              "locationOqid",
              "customerAccountOqid",
              "created"
            ],
            "properties": {
              "sellingPointId": {
                "type": "integer"
              },
              "locationOqid": {
                "type": "string"
              },
              "customerAccountOqid": {
                "type": "string"
              },
              "created": {
                "type": "boolean"
              }
            }
          }
        }
      },
      "CustomerProvisioningRequest": {
        "type": "object",
        "additionalProperties": false,
        "required": [
          "displayName",
          "clientReference"
        ],
        "properties": {
          "displayName": {
            "type": "string",
            "minLength": 1,
            "maxLength": 250
          },
          "clientReference": {
            "type": "string",
            "minLength": 1,
            "maxLength": 256
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "required": [
          "success",
          "message"
        ],
        "properties": {
          "success": {
            "const": false
          },
          "message": {
            "type": "string"
          }
        }
      }
    }
  }
}
