{
  "openapi": "3.1.0",
  "info": {
    "title": "R2 Connect API",
    "version": "1.0.0",
    "summary": "Read-only access to a business running on R2.",
    "description": "Connect accounting software, point of sale or reporting tools to reservations, orders, payments, customers and catalog of a business running on R2. Keys are issued by the business owner with per-resource scopes and can be revoked at any time.",
    "contact": {
      "name": "R2 Developers",
      "url": "https://r2developers.com"
    }
  },
  "servers": [
    {
      "url": "https://api.r2-os.com/api/connect/v1",
      "description": "Production"
    }
  ],
  "security": [
    {
      "bearerAuth": []
    },
    {
      "apiKeyAuth": []
    }
  ],
  "tags": [
    {
      "name": "Account",
      "description": "Which business the key belongs to."
    },
    {
      "name": "Reservations",
      "description": "Lodging stays."
    },
    {
      "name": "Orders",
      "description": "Every commercial transaction."
    },
    {
      "name": "Payments",
      "description": "Collected charges."
    },
    {
      "name": "Customers",
      "description": "Customer and guest directory."
    },
    {
      "name": "Catalog",
      "description": "Everything the business sells."
    }
  ],
  "paths": {
    "/account": {
      "get": {
        "tags": [
          "Account"
        ],
        "operationId": "getAccount",
        "summary": "Account the key belongs to",
        "description": "Requires no scope. Returns the business identity, its currency and the scopes held by the key.",
        "responses": {
          "200": {
            "description": "Account details.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Account"
                    }
                  }
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/reservations": {
      "get": {
        "tags": [
          "Reservations"
        ],
        "operationId": "listReservations",
        "summary": "List lodging reservations",
        "security": [
          {
            "bearerAuth": [
              "read:reservations"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page (1–50).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Cursor from pagination.cursor of the previous page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_from",
            "in": "query",
            "description": "Start date, YYYY-MM-DD (UTC) or epoch milliseconds.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_to",
            "in": "query",
            "description": "End date, inclusive. Same format.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by exact status.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of reservations.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Order"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/reservations/{order_number}": {
      "get": {
        "tags": [
          "Reservations"
        ],
        "operationId": "getReservation",
        "summary": "Retrieve a reservation",
        "security": [
          {
            "bearerAuth": [
              "read:reservations"
            ]
          }
        ],
        "parameters": [
          {
            "name": "order_number",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The reservation.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Order"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/orders": {
      "get": {
        "tags": [
          "Orders"
        ],
        "operationId": "listOrders",
        "summary": "List every order",
        "security": [
          {
            "bearerAuth": [
              "read:orders"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page (1–50).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Cursor from pagination.cursor of the previous page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_from",
            "in": "query",
            "description": "Start date, YYYY-MM-DD (UTC) or epoch milliseconds.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_to",
            "in": "query",
            "description": "End date, inclusive. Same format.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by exact status.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "type",
            "in": "query",
            "description": "Filter by order type.",
            "schema": {
              "type": "string",
              "enum": [
                "booking",
                "space_booking",
                "dine_in",
                "command",
                "takeout",
                "pickup",
                "delivery",
                "room_service"
              ]
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of orders.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Order"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/orders/{order_number}": {
      "get": {
        "tags": [
          "Orders"
        ],
        "operationId": "getOrder",
        "summary": "Retrieve an order",
        "security": [
          {
            "bearerAuth": [
              "read:orders"
            ]
          }
        ],
        "parameters": [
          {
            "name": "order_number",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "The order.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "$ref": "#/components/schemas/Order"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "404": {
            "$ref": "#/components/responses/NotFound"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/payments": {
      "get": {
        "tags": [
          "Payments"
        ],
        "operationId": "listPayments",
        "summary": "List payments",
        "security": [
          {
            "bearerAuth": [
              "read:payments"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "description": "Results per page (1–50).",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Cursor from pagination.cursor of the previous page.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_from",
            "in": "query",
            "description": "Start date, YYYY-MM-DD (UTC) or epoch milliseconds.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "created_to",
            "in": "query",
            "description": "End date, inclusive. Same format.",
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "status",
            "in": "query",
            "description": "Filter by exact status.",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of payments.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Payment"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/guests": {
      "get": {
        "tags": [
          "Customers"
        ],
        "operationId": "listCustomers",
        "summary": "List customers and guests",
        "security": [
          {
            "bearerAuth": [
              "read:guests"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of customers.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/Customer"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    },
    "/items": {
      "get": {
        "tags": [
          "Catalog"
        ],
        "operationId": "listItems",
        "summary": "List catalog items",
        "security": [
          {
            "bearerAuth": [
              "read:items"
            ]
          }
        ],
        "parameters": [
          {
            "name": "limit",
            "in": "query",
            "schema": {
              "type": "integer",
              "minimum": 1,
              "maximum": 50,
              "default": 25
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "schema": {
              "type": "string"
            }
          }
        ],
        "responses": {
          "200": {
            "description": "A page of catalog items.",
            "content": {
              "application/json": {
                "schema": {
                  "type": "object",
                  "properties": {
                    "data": {
                      "type": "array",
                      "items": {
                        "$ref": "#/components/schemas/CatalogItem"
                      }
                    },
                    "pagination": {
                      "$ref": "#/components/schemas/Pagination"
                    }
                  }
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/BadRequest"
          },
          "401": {
            "$ref": "#/components/responses/Unauthorized"
          },
          "403": {
            "$ref": "#/components/responses/Forbidden"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "bearerAuth": {
        "type": "http",
        "scheme": "bearer",
        "description": "Access key issued by the business owner. Starts with r2k_."
      },
      "apiKeyAuth": {
        "type": "apiKey",
        "in": "header",
        "name": "x-api-key",
        "description": "Same key, alternative header."
      }
    },
    "schemas": {
      "Pagination": {
        "type": "object",
        "properties": {
          "cursor": {
            "type": [
              "string",
              "null"
            ],
            "description": "Pass as the cursor parameter to fetch the next page."
          },
          "has_more": {
            "type": "boolean"
          }
        }
      },
      "Account": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "vertical": {
            "type": "string",
            "enum": [
              "hospitality",
              "gastronomy",
              "experience"
            ]
          },
          "currency": {
            "type": "string",
            "description": "ISO 4217."
          },
          "api_version": {
            "type": "string"
          },
          "scopes": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "key_prefix": {
            "type": "string"
          }
        }
      },
      "Tax": {
        "type": "object",
        "properties": {
          "name": {
            "type": "string"
          },
          "rate": {
            "type": [
              "number",
              "null"
            ]
          },
          "amount": {
            "type": "number"
          }
        }
      },
      "OrderLine": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "item_name": {
            "type": "string"
          },
          "quantity": {
            "type": "number"
          },
          "unit_price": {
            "type": "number"
          },
          "line_total": {
            "type": "number"
          },
          "check_in": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "check_out": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "checked_in_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "checked_out_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "Order": {
        "type": "object",
        "description": "A commercial transaction. Exists whether or not it was paid.",
        "properties": {
          "id": {
            "type": "string"
          },
          "order_number": {
            "type": "string",
            "description": "Stable, human-visible number. Use it as your reconciliation key."
          },
          "type": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "pending",
              "placed",
              "confirmed",
              "in-progress",
              "completed",
              "cancelled",
              "noshow",
              "refunded"
            ]
          },
          "channel": {
            "type": [
              "string",
              "null"
            ]
          },
          "guest_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "reservation_title": {
            "type": [
              "string",
              "null"
            ]
          },
          "check_in": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "check_out": {
            "type": [
              "string",
              "null"
            ],
            "format": "date"
          },
          "guests": {
            "type": [
              "object",
              "null"
            ],
            "properties": {
              "adults": {
                "type": "integer"
              },
              "children": {
                "type": "integer"
              }
            }
          },
          "currency": {
            "type": "string"
          },
          "subtotal": {
            "type": "number"
          },
          "discount": {
            "type": "number"
          },
          "taxes": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Tax"
            }
          },
          "tax_total": {
            "type": "number"
          },
          "total": {
            "type": "number"
          },
          "paid": {
            "type": "number",
            "description": "Sum of collected payments."
          },
          "balance": {
            "type": "number",
            "description": "total minus paid."
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "updated_at": {
            "type": "string",
            "format": "date-time"
          },
          "lines": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OrderLine"
            }
          },
          "payments": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Payment"
            }
          }
        }
      },
      "Payment": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "order_id": {
            "type": "string"
          },
          "order_number": {
            "type": [
              "string",
              "null"
            ]
          },
          "amount": {
            "type": "number"
          },
          "currency": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Only succeeded and captured represent collected money."
          },
          "method": {
            "type": "string",
            "enum": [
              "card",
              "cash",
              "transfer",
              "loyalty_points",
              "other"
            ]
          },
          "payment_type": {
            "type": "string",
            "enum": [
              "full",
              "partial",
              "deferred",
              "cash",
              "preauth"
            ]
          },
          "provider": {
            "type": [
              "string",
              "null"
            ]
          },
          "external_id": {
            "type": [
              "string",
              "null"
            ]
          },
          "created_at": {
            "type": "string",
            "format": "date-time"
          },
          "succeeded_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "Customer": {
        "type": "object",
        "description": "Personal data. Handle under the applicable data protection law.",
        "properties": {
          "id": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "email": {
            "type": [
              "string",
              "null"
            ]
          },
          "phone": {
            "type": [
              "string",
              "null"
            ]
          },
          "country": {
            "type": [
              "string",
              "null"
            ]
          },
          "status": {
            "type": "string",
            "enum": [
              "customer",
              "prospect"
            ]
          },
          "visit_count": {
            "type": "integer"
          },
          "total_spent": {
            "type": "number"
          },
          "segment": {
            "type": [
              "string",
              "null"
            ]
          },
          "no_show_count": {
            "type": "integer"
          },
          "first_visit_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          },
          "last_visit_at": {
            "type": [
              "string",
              "null"
            ],
            "format": "date-time"
          }
        }
      },
      "CatalogItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "slug": {
            "type": "string"
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": [
              "string",
              "null"
            ]
          },
          "sku": {
            "type": [
              "string",
              "null"
            ]
          },
          "category_id": {
            "type": "string"
          },
          "category_name": {
            "type": [
              "string",
              "null"
            ]
          },
          "product_type": {
            "type": [
              "string",
              "null"
            ]
          },
          "base_price": {
            "type": "number",
            "description": "List price, before dynamic pricing rules."
          },
          "currency": {
            "type": "string"
          },
          "status": {
            "type": "string"
          }
        }
      },
      "Error": {
        "type": "object",
        "properties": {
          "error": {
            "type": "object",
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "bad_request",
                  "unauthorized",
                  "forbidden",
                  "not_found",
                  "rate_limited",
                  "internal_error"
                ]
              },
              "message": {
                "type": "string"
              }
            }
          }
        }
      }
    },
    "responses": {
      "BadRequest": {
        "description": "A parameter has an invalid format.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Unauthorized": {
        "description": "Missing, invalid or revoked key.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "Forbidden": {
        "description": "The key lacks the required scope.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "NotFound": {
        "description": "No such record in this account.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      },
      "RateLimited": {
        "description": "Rate limit exceeded. Honor the Retry-After header.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/Error"
            }
          }
        }
      }
    }
  }
}