{
  "openapi": "3.0.3",
  "info": {
    "title": "ROS Connect Canonical API",
    "version": "1.0",
    "description": "Canonical partner contract for ROS Connect (`/v1/`).\n\nSignature: HMAC-SHA256 over `timestamp + \".\" + rawBody`.\nHeader: `X-ROS-Signature: sha256=<hex>` plus `X-ROS-Timestamp`, `X-ROS-Event-Id`, `X-ROS-Key-Id`.\nReplay window: 5 minutes. Idempotency required on mutating calls.\n\nSUPPORTED NOW: Native FLOW (adapter demonstration) and Mock restaurant POS (TEST / DEVELOPMENT ONLY).\nDECLARED / NOT CONNECTED: Petpooja, Toast, LucidPOS, Square. Do not treat those as implemented adapters.\n\nGeneric events never create G37 billable lines, G38 invoices, or G39 payments.\n",
    "contact": {
      "name": "RestroSync"
    }
  },
  "servers": [
    {
      "url": "http://localhost:5002",
      "description": "Local development"
    },
    {
      "url": "https://api.restrosync.com",
      "description": "Production API host"
    }
  ],
  "tags": [
    {
      "name": "Events"
    },
    {
      "name": "Commands"
    },
    {
      "name": "Discovery"
    },
    {
      "name": "Webhooks"
    }
  ],
  "security": [
    {
      "RosSignature": []
    }
  ],
  "paths": {
    "/v1/integrations/{integrationId}/events/customer.updated": {
      "post": {
        "tags": [
          "Events"
        ],
        "operationId": "ingestCustomerUpdated",
        "summary": "Inbound customer upsert",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventEnvelope"
              },
              "example": {
                "eventId": "evt_01HDEMOCUSTOMER",
                "eventType": "customer.updated",
                "schemaVersion": "1.0",
                "integrationId": "int_demo_0001",
                "merchantId": "merchant_demo",
                "outletId": "outlet_demo",
                "occurredAt": "2026-08-17T12:00:00.000Z",
                "idempotencyKey": "cust_demo_v1",
                "data": {
                  "externalCustomerId": "cust_demo_1",
                  "mobile": "+910000000099",
                  "firstName": "Asha",
                  "lastName": "Khan",
                  "source": "mock_restaurant_pos"
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/Accepted"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/events/bill.created": {
      "post": {
        "tags": [
          "Events"
        ],
        "operationId": "ingestBillCreated",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventEnvelope"
              },
              "example": {
                "eventId": "evt_01HDEMOBILL",
                "eventType": "bill.created",
                "schemaVersion": "1.0",
                "integrationId": "int_demo_0001",
                "occurredAt": "2026-08-17T12:00:00.000Z",
                "idempotencyKey": "bill_1480_created_v1",
                "data": {
                  "externalBillId": "bill_1480",
                  "billNumber": "MOCK-1480",
                  "items": [
                    {
                      "name": "Chicken Tikka",
                      "quantity": 2,
                      "unitPriceMinor": 50000,
                      "totalMinor": 100000
                    },
                    {
                      "name": "Beer",
                      "quantity": 2,
                      "unitPriceMinor": 15000,
                      "totalMinor": 30000
                    },
                    {
                      "name": "Fries",
                      "quantity": 1,
                      "unitPriceMinor": 18000,
                      "totalMinor": 18000
                    }
                  ],
                  "totalMinor": 148000,
                  "currency": "INR",
                  "status": "COMPLETED",
                  "vendorStatus": "closed",
                  "rosStatus": "COMPLETED"
                }
              }
            }
          }
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/Accepted"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          },
          "422": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/events/bill.updated": {
      "post": {
        "tags": [
          "Events"
        ],
        "operationId": "ingestBillUpdated",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventEnvelope"
              }
            }
          }
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/Accepted"
          },
          "409": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/events/bill.voided": {
      "post": {
        "tags": [
          "Events"
        ],
        "operationId": "ingestBillVoided",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventEnvelope"
              }
            }
          }
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/Accepted"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/events/sale.returned": {
      "post": {
        "tags": [
          "Events"
        ],
        "operationId": "ingestSaleReturned",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventEnvelope"
              }
            }
          }
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/Accepted"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/events/payment-types.updated": {
      "post": {
        "tags": [
          "Events"
        ],
        "operationId": "ingestPaymentTypesUpdated",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventEnvelope"
              }
            }
          }
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/Accepted"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/events/menu.updated": {
      "post": {
        "tags": [
          "Events"
        ],
        "operationId": "ingestMenuUpdated",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventEnvelope"
              }
            }
          }
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/Accepted"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/webhooks": {
      "post": {
        "tags": [
          "Webhooks"
        ],
        "operationId": "ingestGenericWebhook",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/EventEnvelope"
              }
            }
          }
        },
        "responses": {
          "202": {
            "$ref": "#/components/responses/Accepted"
          },
          "401": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/actions/customer.lookup": {
      "post": {
        "tags": [
          "Commands"
        ],
        "operationId": "actionCustomerLookup",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          },
          {
            "$ref": "#/components/parameters/idempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommandEnvelope"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/CommandOk"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/actions/customer.upsert": {
      "post": {
        "tags": [
          "Commands"
        ],
        "operationId": "actionCustomerUpsert",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          },
          {
            "$ref": "#/components/parameters/idempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommandEnvelope"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/CommandOk"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/actions/reward.validate": {
      "post": {
        "tags": [
          "Commands"
        ],
        "operationId": "actionRewardValidate",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          },
          {
            "$ref": "#/components/parameters/idempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommandEnvelope"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/CommandOk"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/actions/reward.redeem": {
      "post": {
        "tags": [
          "Commands"
        ],
        "operationId": "actionRewardRedeem",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          },
          {
            "$ref": "#/components/parameters/idempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommandEnvelope"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/CommandOk"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/actions/reward.revert": {
      "post": {
        "tags": [
          "Commands"
        ],
        "operationId": "actionRewardRevert",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          },
          {
            "$ref": "#/components/parameters/idempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommandEnvelope"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/CommandOk"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/actions/menu.push": {
      "post": {
        "tags": [
          "Commands"
        ],
        "operationId": "actionMenuPush",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          },
          {
            "$ref": "#/components/parameters/idempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommandEnvelope"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/CommandOk"
          },
          "403": {
            "$ref": "#/components/responses/Error"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/actions/payment-types.push": {
      "post": {
        "tags": [
          "Commands"
        ],
        "operationId": "actionPaymentTypesPush",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          },
          {
            "$ref": "#/components/parameters/idempotencyKey"
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CommandEnvelope"
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/CommandOk"
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/capabilities": {
      "get": {
        "tags": [
          "Discovery"
        ],
        "operationId": "getCapabilities",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          }
        ],
        "responses": {
          "200": {
            "description": "Capability flags",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success"
                }
              }
            }
          }
        }
      }
    },
    "/v1/integrations/{integrationId}/health": {
      "get": {
        "tags": [
          "Discovery"
        ],
        "operationId": "getHealth",
        "parameters": [
          {
            "$ref": "#/components/parameters/integrationId"
          }
        ],
        "responses": {
          "200": {
            "description": "Health",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/Success"
                }
              }
            }
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "RosSignature": {
        "type": "apiKey",
        "in": "header",
        "name": "X-ROS-Signature",
        "description": "HMAC-SHA256. Value format sha256=<hex> of timestamp + \".\" + raw body."
      }
    },
    "parameters": {
      "integrationId": {
        "name": "integrationId",
        "in": "path",
        "required": true,
        "schema": {
          "type": "string",
          "example": "int_demo_0001"
        }
      },
      "idempotencyKey": {
        "name": "Idempotency-Key",
        "in": "header",
        "required": false,
        "schema": {
          "type": "string"
        }
      }
    },
    "responses": {
      "Accepted": {
        "description": "Event accepted",
        "headers": {
          "X-Request-Id": {
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Success"
            }
          }
        }
      },
      "CommandOk": {
        "description": "Command result",
        "headers": {
          "X-Request-Id": {
            "schema": {
              "type": "string"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Success"
            }
          }
        }
      },
      "Error": {
        "description": "Canonical error",
        "headers": {
          "Retry-After": {
            "schema": {
              "type": "integer"
            }
          }
        },
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/ErrorResponse"
            },
            "examples": {
              "signature": {
                "value": {
                  "success": false,
                  "error": {
                    "code": "SIGNATURE_INVALID",
                    "message": "Invalid signature",
                    "requestId": "req_demo"
                  }
                }
              },
              "duplicate": {
                "value": {
                  "success": false,
                  "error": {
                    "code": "DUPLICATE_EVENT",
                    "message": "Event already accepted",
                    "requestId": "req_demo"
                  }
                }
              },
              "conflict": {
                "value": {
                  "success": false,
                  "error": {
                    "code": "IDEMPOTENCY_CONFLICT",
                    "message": "Idempotency key reused with a different payload"
                  }
                }
              },
              "capability": {
                "value": {
                  "success": false,
                  "error": {
                    "code": "UNSUPPORTED_CAPABILITY",
                    "message": "Scope menu.write is not granted"
                  }
                }
              }
            }
          }
        }
      }
    },
    "schemas": {
      "Success": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "example": true
          },
          "data": {
            "type": "object"
          }
        }
      },
      "Error": {
        "type": "object",
        "required": [
          "code",
          "message"
        ],
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "AUTHENTICATION_FAILED",
              "SIGNATURE_INVALID",
              "SIGNATURE_EXPIRED",
              "REPLAY_DETECTED",
              "INVALID_SCHEMA",
              "INVALID_FIELD",
              "MISSING_REQUIRED_FIELD",
              "UNSUPPORTED_CAPABILITY",
              "INTEGRATION_NOT_FOUND",
              "INTEGRATION_NOT_CONNECTED",
              "INTEGRATION_DISABLED",
              "DUPLICATE_EVENT",
              "STALE_EVENT",
              "RATE_LIMITED",
              "PROVIDER_TIMEOUT",
              "PROVIDER_ERROR",
              "IDEMPOTENCY_CONFLICT",
              "INTERNAL_ERROR"
            ]
          },
          "message": {
            "type": "string"
          },
          "details": {},
          "requestId": {
            "type": "string"
          },
          "retryable": {
            "type": "boolean"
          },
          "providerCode": {
            "type": "string"
          }
        }
      },
      "ErrorResponse": {
        "type": "object",
        "properties": {
          "success": {
            "type": "boolean",
            "example": false
          },
          "error": {
            "$ref": "#/components/schemas/Error"
          }
        }
      },
      "EventEnvelope": {
        "type": "object",
        "required": [
          "eventId",
          "eventType",
          "schemaVersion",
          "integrationId",
          "occurredAt",
          "idempotencyKey",
          "data"
        ],
        "properties": {
          "eventId": {
            "type": "string"
          },
          "eventType": {
            "type": "string",
            "enum": [
              "customer.updated",
              "bill.created",
              "bill.updated",
              "bill.voided",
              "sale.returned",
              "payment-types.updated",
              "menu.updated"
            ]
          },
          "schemaVersion": {
            "type": "string",
            "example": "1.0"
          },
          "integrationId": {
            "type": "string"
          },
          "merchantId": {
            "type": "string"
          },
          "outletId": {
            "type": "string"
          },
          "occurredAt": {
            "type": "string",
            "format": "date-time"
          },
          "receivedAt": {
            "type": "string",
            "format": "date-time"
          },
          "idempotencyKey": {
            "type": "string"
          },
          "data": {
            "type": "object"
          }
        }
      },
      "CommandEnvelope": {
        "type": "object",
        "required": [
          "commandId",
          "action",
          "schemaVersion",
          "integrationId",
          "idempotencyKey",
          "requestedAt",
          "data"
        ],
        "properties": {
          "commandId": {
            "type": "string"
          },
          "action": {
            "type": "string",
            "enum": [
              "customer.lookup",
              "customer.upsert",
              "reward.validate",
              "reward.redeem",
              "reward.revert",
              "menu.push",
              "payment-types.push"
            ]
          },
          "schemaVersion": {
            "type": "string",
            "example": "1.0"
          },
          "integrationId": {
            "type": "string"
          },
          "merchantId": {
            "type": "string"
          },
          "outletId": {
            "type": "string"
          },
          "idempotencyKey": {
            "type": "string"
          },
          "requestedAt": {
            "type": "string",
            "format": "date-time"
          },
          "data": {
            "type": "object"
          }
        }
      },
      "ExternalCustomer": {
        "type": "object",
        "required": [
          "externalCustomerId"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string"
          },
          "externalCustomerId": {
            "type": "string"
          },
          "sourceCustomerId": {
            "type": "string"
          },
          "merchantId": {
            "type": "string"
          },
          "mobile": {
            "type": "string",
            "example": "+910000000099"
          },
          "email": {
            "type": "string"
          },
          "firstName": {
            "type": "string"
          },
          "lastName": {
            "type": "string"
          },
          "gender": {
            "type": "string"
          },
          "dateOfBirth": {
            "type": "string"
          },
          "preferences": {
            "type": "object"
          },
          "source": {
            "type": "string"
          },
          "createdAt": {
            "type": "string"
          },
          "updatedAt": {
            "type": "string"
          }
        }
      },
      "ExternalBill": {
        "type": "object",
        "required": [
          "externalBillId",
          "totalMinor",
          "currency"
        ],
        "properties": {
          "schemaVersion": {
            "type": "string"
          },
          "externalBillId": {
            "type": "string"
          },
          "billNumber": {
            "type": "string"
          },
          "outletId": {
            "type": "string"
          },
          "merchantId": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BillItem"
            }
          },
          "totalMinor": {
            "type": "integer",
            "example": 148000
          },
          "currency": {
            "type": "string",
            "example": "INR"
          },
          "status": {
            "type": "string"
          },
          "vendorStatus": {
            "type": "string"
          },
          "rosStatus": {
            "type": "string",
            "enum": [
              "OPEN",
              "COMPLETED",
              "VOIDED",
              "RETURNED",
              "PARTIALLY_RETURNED"
            ]
          },
          "revision": {
            "type": "integer"
          }
        }
      },
      "BillItem": {
        "type": "object",
        "required": [
          "name",
          "quantity",
          "unitPriceMinor",
          "totalMinor"
        ],
        "properties": {
          "name": {
            "type": "string",
            "example": "Chicken Tikka"
          },
          "quantity": {
            "type": "number"
          },
          "unitPriceMinor": {
            "type": "integer"
          },
          "totalMinor": {
            "type": "integer"
          },
          "sku": {
            "type": "string"
          },
          "category": {
            "type": "string"
          }
        }
      },
      "ExternalTransaction": {
        "type": "object",
        "required": [
          "externalTransactionId",
          "amountMinor",
          "currency",
          "transactionType",
          "occurredAt"
        ],
        "properties": {
          "externalTransactionId": {
            "type": "string"
          },
          "billId": {
            "type": "string"
          },
          "amountMinor": {
            "type": "integer"
          },
          "currency": {
            "type": "string"
          },
          "transactionType": {
            "type": "string",
            "enum": [
              "SALE",
              "RETURN",
              "VOID",
              "ADJUSTMENT"
            ]
          },
          "occurredAt": {
            "type": "string"
          },
          "source": {
            "type": "string"
          }
        }
      },
      "PaymentTypes": {
        "type": "object",
        "properties": {
          "schemaVersion": {
            "type": "string"
          },
          "categories": {
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "name": {
                  "type": "string"
                },
                "canonicalType": {
                  "type": "string"
                },
                "types": {
                  "type": "array",
                  "items": {
                    "type": "string"
                  }
                }
              }
            }
          }
        }
      },
      "ExternalMenu": {
        "type": "object",
        "properties": {
          "menuVersion": {
            "type": "string"
          },
          "externalMenuVersion": {
            "type": "string"
          },
          "mappingVersion": {
            "type": "string"
          },
          "categories": {
            "type": "array",
            "items": {}
          },
          "items": {
            "type": "array",
            "items": {}
          }
        }
      }
    }
  },
  "x-ros-connect": {
    "deprecation": {
      "policy": "v1 field meanings do not change. Breaking changes ship as /v2/.",
      "headers": "Sunset, Deprecation"
    },
    "rateLimits": {
      "webhook": "30 per minute per integration",
      "commands": "30 per minute per integration",
      "retryAfter": 60
    },
    "supportedNow": [
      "native_flow",
      "mock_restaurant_pos"
    ],
    "declaredNotConnected": [
      "petpooja",
      "toast",
      "lucid",
      "square"
    ]
  }
}