{
  "openapi": "3.0.3",
  "info": {
    "title": "LivingSocial Partner API",
    "version": "1.0.0",
    "description": "Pull eligible Groupon US offers into your own storefront, keep a shopper's cart in sync, and read the order after Groupon's checkout.\n\nAuthenticate every request with `Authorization: Bearer <your API key>`. Create keys on the Storefronts and keys page of this site. Call the API from your server, never from a browser or an app.\n\nEvery error carries `details.error`, the code to branch on. Money is an integer in minor units; divide by 10^`currencyPrecision` to display."
  },
  "servers": [
    {
      "url": "https://api-core.livingsocial.com",
      "description": "LivingSocial Partner API"
    }
  ],
  "tags": [
    {
      "name": "partner_storefront",
      "description": "Products, carts and bookings"
    }
  ],
  "paths": {
    "/partner_storefront/bookings/{bookingId}": {
      "get": {
        "tags": [
          "partner_storefront"
        ],
        "operationId": "partner_storefront_bookingGet",
        "summary": "Read an order: its status and one voucher link per purchased unit.",
        "description": "Read an order: its status and one voucher link per purchased unit. `bookingId` is the\n`grouponOrderUuid` Groupon adds to your redirect URL. Poll while the status is ON_HOLD or\nPENDING (2, 4, 8, 15, 30 seconds). A read never changes the order, so it is always safe to retry.\n\n**Errors:** notFound (INVALID_BOOKING_UUID) for an order not placed from this storefront's carts.",
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/BookingGetResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/APIError"
          },
          "401": {
            "$ref": "#/components/responses/APIError"
          },
          "404": {
            "description": "notFound (INVALID_BOOKING_UUID) for an order not placed from this storefront's carts.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/APIError"
          }
        },
        "parameters": [
          {
            "name": "bookingId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-request-id",
            "in": "header",
            "required": false,
            "description": "A UUID you make per request. Groupon echoes it back as `details.requestId` in every error body that carries `details.error`; a value that is not a UUID is replaced by one Groupon makes.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "Authorization": []
          }
        ]
      }
    },
    "/partner_storefront/carts/{cartId}": {
      "delete": {
        "tags": [
          "partner_storefront"
        ],
        "operationId": "partner_storefront_cartAbandon",
        "summary": "Abandon a cart.",
        "description": "Abandon a cart. Discard its id afterwards: adding to an abandoned cart silently starts a new,\nempty one under the same id.\n\n**Errors:** notFound (INVALID_CART_ID) for a cart this storefront never created.",
        "responses": {
          "204": {
            "description": "No Content"
          },
          "400": {
            "$ref": "#/components/responses/APIError"
          },
          "401": {
            "$ref": "#/components/responses/APIError"
          },
          "404": {
            "description": "notFound (INVALID_CART_ID) for a cart this storefront never created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/APIError"
          }
        },
        "parameters": [
          {
            "name": "cartId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-request-id",
            "in": "header",
            "required": false,
            "description": "A UUID you make per request. Groupon echoes it back as `details.requestId` in every error body that carries `details.error`; a value that is not a UUID is replaced by one Groupon makes.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "Authorization": []
          }
        ]
      },
      "get": {
        "tags": [
          "partner_storefront"
        ],
        "operationId": "partner_storefront_cartGet",
        "summary": "Read a cart.",
        "description": "Read a cart. Call it when your cart page loads and before showing Buy now after a long idle.\nA cart that no longer exists reads as an empty cart (`itemCount: 0`).\n\n**Errors:** notFound (INVALID_CART_ID) for a cart this storefront never created.",
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CartGetResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/APIError"
          },
          "401": {
            "$ref": "#/components/responses/APIError"
          },
          "404": {
            "description": "notFound (INVALID_CART_ID) for a cart this storefront never created.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/APIError"
          }
        },
        "parameters": [
          {
            "name": "cartId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-request-id",
            "in": "header",
            "required": false,
            "description": "A UUID you make per request. Groupon echoes it back as `details.requestId` in every error body that carries `details.error`; a value that is not a UUID is replaced by one Groupon makes.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "Authorization": []
          }
        ]
      }
    },
    "/partner_storefront/carts": {
      "post": {
        "tags": [
          "partner_storefront"
        ],
        "operationId": "partner_storefront_cartCreate",
        "summary": "Create a cart with its first items.",
        "description": "Create a cart with its first items. Store the returned `id` against the shopper's session and\nuse the latest `buyLink` verbatim as the Buy now link. A retry after a failure is harmless: it\ncreates a separate new cart.\n\n**Returns:** the full cart.\n**Errors:** invalidArgument (BAD_REQUEST); notFound (INVALID_PRODUCT_ID);\nfailedPrecondition (PRODUCT_NOT_CARTABLE, CART_ITEM_LIMIT); aborted (PRICE_MISMATCH, the live\nprice in `details.currentPrice`).",
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CartCreateResponse"
                }
              }
            }
          },
          "400": {
            "description": "invalidArgument (BAD_REQUEST); notFound (INVALID_PRODUCT_ID); failedPrecondition (PRODUCT_NOT_CARTABLE, CART_ITEM_LIMIT); aborted (PRICE_MISMATCH, the live price in `details.currentPrice`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/APIError"
          },
          "404": {
            "description": "invalidArgument (BAD_REQUEST); notFound (INVALID_PRODUCT_ID); failedPrecondition (PRODUCT_NOT_CARTABLE, CART_ITEM_LIMIT); aborted (PRICE_MISMATCH, the live price in `details.currentPrice`).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/APIError"
          }
        },
        "parameters": [
          {
            "name": "x-request-id",
            "in": "header",
            "required": false,
            "description": "A UUID you make per request. Groupon echoes it back as `details.requestId` in every error body that carries `details.error`; a value that is not a UUID is replaced by one Groupon makes.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CartCreateRequestBody"
              }
            }
          }
        },
        "security": [
          {
            "Authorization": []
          }
        ]
      }
    },
    "/partner_storefront/carts/{cartId}/items/{itemId}": {
      "delete": {
        "tags": [
          "partner_storefront"
        ],
        "operationId": "partner_storefront_cartItemRemove",
        "summary": "Remove a line.",
        "description": "Remove a line. Removing the last one keeps the cart, with `itemCount: 0`.\n\n**Errors:** notFound (INVALID_PRODUCT_ID) when the cart has no such line.",
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CartItemRemoveResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/APIError"
          },
          "401": {
            "$ref": "#/components/responses/APIError"
          },
          "404": {
            "description": "notFound (INVALID_PRODUCT_ID) when the cart has no such line.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/APIError"
          }
        },
        "parameters": [
          {
            "name": "cartId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-request-id",
            "in": "header",
            "required": false,
            "description": "A UUID you make per request. Groupon echoes it back as `details.requestId` in every error body that carries `details.error`; a value that is not a UUID is replaced by one Groupon makes.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "Authorization": []
          }
        ]
      },
      "patch": {
        "tags": [
          "partner_storefront"
        ],
        "operationId": "partner_storefront_cartItemUpdate",
        "summary": "Set a line's quantity (1-100).",
        "description": "Set a line's quantity (1-100). The quantity is absolute, not a change, so a retry is safe.\n`itemId` is the line's id, which equals its `optionId`.\n\n**Errors:** notFound (INVALID_PRODUCT_ID) when the cart has no such line;\naborted (PRICE_MISMATCH) when `expectedPrice` is stale.",
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CartItemUpdateResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/APIError"
          },
          "401": {
            "$ref": "#/components/responses/APIError"
          },
          "404": {
            "description": "notFound (INVALID_PRODUCT_ID) when the cart has no such line; aborted (PRICE_MISMATCH) when `expectedPrice` is stale.",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/APIError"
          }
        },
        "parameters": [
          {
            "name": "cartId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "itemId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-request-id",
            "in": "header",
            "required": false,
            "description": "A UUID you make per request. Groupon echoes it back as `details.requestId` in every error body that carries `details.error`; a value that is not a UUID is replaced by one Groupon makes.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CartItemUpdateRequestBody"
              }
            }
          }
        },
        "security": [
          {
            "Authorization": []
          }
        ]
      }
    },
    "/partner_storefront/carts/{cartId}/items": {
      "post": {
        "tags": [
          "partner_storefront"
        ],
        "operationId": "partner_storefront_cartItemsAdd",
        "summary": "Add items.",
        "description": "Add items. On a timeout, read the cart and add only what is missing; never retry blindly.\nA 200 does not promise every item was added: compare `items` with what you asked for and read\n`messages` for `item_declined`.\n\n**Errors:** as for creating a cart, plus notFound (INVALID_CART_ID).",
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/CartItemsAddResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/APIError"
          },
          "401": {
            "$ref": "#/components/responses/APIError"
          },
          "404": {
            "description": "as for creating a cart, plus notFound (INVALID_CART_ID).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/APIError"
          }
        },
        "parameters": [
          {
            "name": "cartId",
            "in": "path",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-request-id",
            "in": "header",
            "required": false,
            "description": "A UUID you make per request. Groupon echoes it back as `details.requestId` in every error body that carries `details.error`; a value that is not a UUID is replaced by one Groupon makes.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "requestBody": {
          "required": true,
          "content": {
            "application/json": {
              "schema": {
                "$ref": "#/components/schemas/CartItemsAddRequestBody"
              }
            }
          }
        },
        "security": [
          {
            "Authorization": []
          }
        ]
      }
    },
    "/partner_storefront/products": {
      "get": {
        "tags": [
          "partner_storefront"
        ],
        "operationId": "partner_storefront_productsList",
        "summary": "One page of deals.",
        "description": "One page of deals. Walk the whole catalog once, then pull only what changed with\n`updatedSince`; send every other parameter unchanged on every page of one walk and pass\n`nextCursor` back as `cursor` until `hasMore` is false. `timestamp` is on the final page only.\n\n**Returns:** one page: `data`, `nextCursor`, `hasMore`, and on the last page `timestamp`.\n**Errors:** invalidArgument (BAD_REQUEST) for a bad filter or cursor; permissionDenied\n(FORBIDDEN) outside the storefront's scope; resourceExhausted (RATE_LIMITED); unavailable\n(UPSTREAM_UNAVAILABLE).",
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/ProductsListResponse"
                }
              }
            }
          },
          "400": {
            "description": "invalidArgument (BAD_REQUEST) for a bad filter or cursor; permissionDenied (FORBIDDEN) outside the storefront's scope; resourceExhausted (RATE_LIMITED); unavailable (UPSTREAM_UNAVAILABLE).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIErrorResponse"
                }
              }
            }
          },
          "401": {
            "$ref": "#/components/responses/APIError"
          },
          "403": {
            "description": "invalidArgument (BAD_REQUEST) for a bad filter or cursor; permissionDenied (FORBIDDEN) outside the storefront's scope; resourceExhausted (RATE_LIMITED); unavailable (UPSTREAM_UNAVAILABLE).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIErrorResponse"
                }
              }
            }
          },
          "429": {
            "description": "invalidArgument (BAD_REQUEST) for a bad filter or cursor; permissionDenied (FORBIDDEN) outside the storefront's scope; resourceExhausted (RATE_LIMITED); unavailable (UPSTREAM_UNAVAILABLE).",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/APIErrorResponse"
                }
              }
            }
          },
          "500": {
            "$ref": "#/components/responses/APIError"
          }
        },
        "parameters": [
          {
            "name": "active",
            "in": "query",
            "description": "Filter on the deal's active flag. Never send it on a delta walk: you need the deactivations.",
            "required": false,
            "schema": {
              "type": "boolean"
            }
          },
          {
            "name": "category0",
            "in": "query",
            "description": "Category permalink at depth 0: `local`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category1",
            "in": "query",
            "description": "Category permalink at depth 1, such as `things-to-do`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "category2",
            "in": "query",
            "description": "Category permalink at depth 2, such as `massage`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "country",
            "in": "query",
            "description": "ISO 3166-1 alpha-2. Only `US` inventory is exposed today.",
            "required": true,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "cursor",
            "in": "query",
            "description": "Opaque boundary from the previous page's `nextCursor`. Omitted for the first page.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "limit",
            "in": "query",
            "description": "Page size. Clamped by the repository to `CURSOR_PAGINATION_DEFAULTS.maxLimit`.",
            "required": false,
            "schema": {
              "type": "number"
            }
          },
          {
            "name": "state",
            "in": "query",
            "description": "Full US state name, exactly as listed (case-sensitive), such as `Illinois`.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "updatedSince",
            "in": "query",
            "description": "Only deals whose price or content changed at or after this instant.",
            "required": false,
            "schema": {
              "type": "string"
            }
          },
          {
            "name": "x-request-id",
            "in": "header",
            "required": false,
            "description": "A UUID you make per request. Groupon echoes it back as `details.requestId` in every error body that carries `details.error`; a value that is not a UUID is replaced by one Groupon makes.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "Authorization": []
          }
        ]
      }
    },
    "/partner_storefront/me": {
      "get": {
        "tags": [
          "partner_storefront"
        ],
        "operationId": "partner_storefront_storefrontMe",
        "summary": "Read your storefront's registration: its partner id, scope, logo and redirect URL, CJ publisher id and status.",
        "description": "Read your storefront's registration: its partner id, scope, logo and redirect URL, CJ\npublisher id and status. Use it to confirm a key is the storefront you think it is.",
        "responses": {
          "200": {
            "description": "Successful response",
            "content": {
              "application/json": {
                "schema": {
                  "$ref": "#/components/schemas/StorefrontMeResponse"
                }
              }
            }
          },
          "400": {
            "$ref": "#/components/responses/APIError"
          },
          "401": {
            "$ref": "#/components/responses/APIError"
          },
          "500": {
            "$ref": "#/components/responses/APIError"
          }
        },
        "parameters": [
          {
            "name": "x-request-id",
            "in": "header",
            "required": false,
            "description": "A UUID you make per request. Groupon echoes it back as `details.requestId` in every error body that carries `details.error`; a value that is not a UUID is replaced by one Groupon makes.",
            "schema": {
              "type": "string",
              "format": "uuid"
            }
          }
        ],
        "security": [
          {
            "Authorization": []
          }
        ]
      }
    }
  },
  "components": {
    "schemas": {
      "CurrencyCodeString": {
        "type": "string"
      },
      "BookingGetResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The `grouponOrderUuid` Groupon adds to the redirect URL."
          },
          "status": {
            "type": "string",
            "description": "Known values: ON_HOLD, PENDING (poll again), CONFIRMED, REDEEMED (paid), REJECTED, EXPIRED\n(not paid), CANCELLED. Treat any other value as unresolved."
          },
          "supplierReference": {
            "type": "string",
            "nullable": true
          },
          "createdAt": {
            "type": "string"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BookingItem"
            }
          }
        },
        "required": [
          "id",
          "status",
          "supplierReference",
          "createdAt",
          "items"
        ]
      },
      "CartCreateResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Known values: ACTIVE, LOCKED, CHECKED_OUT, EXPIRED, ABANDONED."
          },
          "buyLink": {
            "type": "string",
            "description": "Groupon's checkout for this cart. Use the latest one verbatim as the Buy now link."
          },
          "country": {
            "type": "string"
          },
          "currency": {
            "$ref": "#/components/schemas/CurrencyCodeString"
          },
          "clientReference": {
            "type": "string",
            "nullable": true
          },
          "itemCount": {
            "type": "number"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CartLine"
            }
          },
          "totals": {
            "$ref": "#/components/schemas/CartTotals"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CartMessage"
            }
          },
          "createdAt": {
            "type": "string",
            "nullable": true
          },
          "updatedAt": {
            "type": "string",
            "nullable": true
          },
          "expiresAt": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "status",
          "buyLink",
          "country",
          "currency",
          "clientReference",
          "itemCount",
          "items",
          "totals",
          "messages",
          "createdAt",
          "updatedAt",
          "expiresAt"
        ]
      },
      "CartGetResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Known values: ACTIVE, LOCKED, CHECKED_OUT, EXPIRED, ABANDONED."
          },
          "buyLink": {
            "type": "string",
            "description": "Groupon's checkout for this cart. Use the latest one verbatim as the Buy now link."
          },
          "country": {
            "type": "string"
          },
          "currency": {
            "$ref": "#/components/schemas/CurrencyCodeString"
          },
          "clientReference": {
            "type": "string",
            "nullable": true
          },
          "itemCount": {
            "type": "number"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CartLine"
            }
          },
          "totals": {
            "$ref": "#/components/schemas/CartTotals"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CartMessage"
            }
          },
          "createdAt": {
            "type": "string",
            "nullable": true
          },
          "updatedAt": {
            "type": "string",
            "nullable": true
          },
          "expiresAt": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "status",
          "buyLink",
          "country",
          "currency",
          "clientReference",
          "itemCount",
          "items",
          "totals",
          "messages",
          "createdAt",
          "updatedAt",
          "expiresAt"
        ]
      },
      "CartItemRemoveResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Known values: ACTIVE, LOCKED, CHECKED_OUT, EXPIRED, ABANDONED."
          },
          "buyLink": {
            "type": "string",
            "description": "Groupon's checkout for this cart. Use the latest one verbatim as the Buy now link."
          },
          "country": {
            "type": "string"
          },
          "currency": {
            "$ref": "#/components/schemas/CurrencyCodeString"
          },
          "clientReference": {
            "type": "string",
            "nullable": true
          },
          "itemCount": {
            "type": "number"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CartLine"
            }
          },
          "totals": {
            "$ref": "#/components/schemas/CartTotals"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CartMessage"
            }
          },
          "createdAt": {
            "type": "string",
            "nullable": true
          },
          "updatedAt": {
            "type": "string",
            "nullable": true
          },
          "expiresAt": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "status",
          "buyLink",
          "country",
          "currency",
          "clientReference",
          "itemCount",
          "items",
          "totals",
          "messages",
          "createdAt",
          "updatedAt",
          "expiresAt"
        ]
      },
      "CartItemUpdateResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Known values: ACTIVE, LOCKED, CHECKED_OUT, EXPIRED, ABANDONED."
          },
          "buyLink": {
            "type": "string",
            "description": "Groupon's checkout for this cart. Use the latest one verbatim as the Buy now link."
          },
          "country": {
            "type": "string"
          },
          "currency": {
            "$ref": "#/components/schemas/CurrencyCodeString"
          },
          "clientReference": {
            "type": "string",
            "nullable": true
          },
          "itemCount": {
            "type": "number"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CartLine"
            }
          },
          "totals": {
            "$ref": "#/components/schemas/CartTotals"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CartMessage"
            }
          },
          "createdAt": {
            "type": "string",
            "nullable": true
          },
          "updatedAt": {
            "type": "string",
            "nullable": true
          },
          "expiresAt": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "status",
          "buyLink",
          "country",
          "currency",
          "clientReference",
          "itemCount",
          "items",
          "totals",
          "messages",
          "createdAt",
          "updatedAt",
          "expiresAt"
        ]
      },
      "CartItemsAddResponse": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "Known values: ACTIVE, LOCKED, CHECKED_OUT, EXPIRED, ABANDONED."
          },
          "buyLink": {
            "type": "string",
            "description": "Groupon's checkout for this cart. Use the latest one verbatim as the Buy now link."
          },
          "country": {
            "type": "string"
          },
          "currency": {
            "$ref": "#/components/schemas/CurrencyCodeString"
          },
          "clientReference": {
            "type": "string",
            "nullable": true
          },
          "itemCount": {
            "type": "number"
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CartLine"
            }
          },
          "totals": {
            "$ref": "#/components/schemas/CartTotals"
          },
          "messages": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CartMessage"
            }
          },
          "createdAt": {
            "type": "string",
            "nullable": true
          },
          "updatedAt": {
            "type": "string",
            "nullable": true
          },
          "expiresAt": {
            "type": "string",
            "nullable": true
          }
        },
        "required": [
          "id",
          "status",
          "buyLink",
          "country",
          "currency",
          "clientReference",
          "itemCount",
          "items",
          "totals",
          "messages",
          "createdAt",
          "updatedAt",
          "expiresAt"
        ]
      },
      "ProductsListResponse": {
        "type": "object",
        "properties": {
          "hasMore": {
            "type": "boolean",
            "description": "True while more pages remain. Keep paging until false, even after an empty page."
          },
          "timestamp": {
            "type": "string",
            "description": "Groupon's clock on the final page of a walk: the base of the next `updatedSince`."
          },
          "data": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/Product"
            }
          },
          "nextCursor": {
            "type": "string",
            "nullable": true,
            "description": "Boundary for the next page, or null when the feed is exhausted."
          }
        },
        "required": [
          "hasMore",
          "data",
          "nextCursor"
        ]
      },
      "StorefrontMeResponse": {
        "type": "object",
        "properties": {
          "storefront": {
            "$ref": "#/components/schemas/StorefrontRegistration"
          }
        },
        "required": [
          "storefront"
        ]
      },
      "BookingItem": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string",
            "nullable": true,
            "description": "null when the deal has since left Groupon's catalog; `optionId` still names what was bought."
          },
          "optionId": {
            "type": "string"
          },
          "quantity": {
            "type": "number"
          },
          "status": {
            "type": "string",
            "description": "The item's status, same values as the order's."
          },
          "unitItems": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/BookingUnitItem"
            }
          }
        },
        "required": [
          "productId",
          "optionId",
          "quantity",
          "status",
          "unitItems"
        ],
        "description": "One product and option bought in an order."
      },
      "BookingUnitItem": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "status": {
            "type": "string",
            "description": "The voucher's status, same values as the order's. CANCELLED means cancelled or refunded."
          },
          "myGrouponUrl": {
            "type": "string",
            "description": "Where the shopper views and redeems the voucher, after signing in to Groupon."
          }
        },
        "required": [
          "id",
          "status",
          "myGrouponUrl"
        ],
        "description": "One voucher of an order item."
      },
      "CartItemInput": {
        "type": "object",
        "properties": {
          "productId": {
            "type": "string"
          },
          "optionId": {
            "type": "string"
          },
          "quantity": {
            "type": "number",
            "description": "1 to 100."
          },
          "expectedPrice": {
            "type": "number",
            "description": "The per-unit retail your site shows, in minor units. Strongly recommended."
          }
        },
        "required": [
          "productId",
          "optionId",
          "quantity"
        ],
        "description": "One line to add to a cart."
      },
      "CartLine": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "productId": {
            "type": "string"
          },
          "optionId": {
            "type": "string"
          },
          "title": {
            "type": "string",
            "nullable": true
          },
          "optionTitle": {
            "type": "string",
            "nullable": true
          },
          "media": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductMedia"
            }
          },
          "quantity": {
            "type": "number"
          },
          "available": {
            "type": "boolean"
          },
          "unavailableReason": {
            "type": "string",
            "nullable": true,
            "description": "Why the line cannot be bought (known values: SOLD_OUT, DEAL_ENDED, OPTION_REMOVED); null when it can."
          },
          "price": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Price"
              }
            ],
            "nullable": true,
            "description": "null when the live price could not be read (see `messages`); such a line is not in the totals."
          },
          "lineTotal": {
            "type": "number",
            "nullable": true,
            "description": "`price.retail * quantity`, or null with the price."
          }
        },
        "required": [
          "id",
          "productId",
          "optionId",
          "title",
          "optionTitle",
          "media",
          "quantity",
          "available",
          "unavailableReason",
          "price",
          "lineTotal"
        ],
        "description": "One line of a cart. Its `id` equals its `optionId`."
      },
      "CartMessage": {
        "type": "object",
        "properties": {
          "type": {
            "type": "string"
          },
          "code": {
            "type": "string"
          },
          "content": {
            "type": "string"
          },
          "path": {
            "type": "string"
          }
        },
        "required": [
          "type",
          "code",
          "content",
          "path"
        ],
        "description": "A non-fatal note about this response, such as `item_declined` or `price_unavailable`."
      },
      "CartTotals": {
        "type": "object",
        "properties": {
          "subtotal": {
            "type": "number"
          },
          "savings": {
            "type": "number"
          },
          "grandTotal": {
            "type": "number"
          },
          "currency": {
            "$ref": "#/components/schemas/CurrencyCodeString"
          },
          "currencyPrecision": {
            "type": "number"
          }
        },
        "required": [
          "subtotal",
          "savings",
          "grandTotal",
          "currency",
          "currencyPrecision"
        ],
        "description": "Cart totals in minor units, before tax and promo codes."
      },
      "OptionSelection": {
        "type": "object",
        "properties": {
          "attributeId": {
            "type": "string"
          },
          "title": {
            "type": "string"
          },
          "required": {
            "type": "boolean"
          },
          "values": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OptionSelectionValue"
            }
          }
        },
        "required": [
          "attributeId",
          "title",
          "required",
          "values"
        ],
        "description": "A choose-one attribute of an option (a size, a date slot label). Most options have none."
      },
      "OptionSelectionValue": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string"
          },
          "title": {
            "type": "string"
          }
        },
        "required": [
          "id",
          "title"
        ]
      },
      "Price": {
        "type": "object",
        "properties": {
          "retail": {
            "type": "number",
            "description": "What the shopper pays per unit. Send it as `expectedPrice` on cart lines."
          },
          "original": {
            "type": "number",
            "description": "The strike-through price."
          },
          "currency": {
            "$ref": "#/components/schemas/CurrencyCodeString"
          },
          "currencyPrecision": {
            "type": "number",
            "description": "Decimal places: display amount = amount / 10^currencyPrecision."
          }
        },
        "required": [
          "retail",
          "original",
          "currency",
          "currencyPrecision"
        ],
        "description": "A per-unit price, in minor units."
      },
      "Product": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The `productId` of a cart line."
          },
          "title": {
            "type": "string"
          },
          "shortDescription": {
            "type": "string"
          },
          "description": {
            "type": "string",
            "description": "Plain text."
          },
          "status": {
            "type": "string",
            "description": "Known values: active, sold_out, expired. List a product only when it is active."
          },
          "availabilityRequired": {
            "type": "boolean",
            "description": "true means the deal needs a time-slot booking and cannot be added to a cart."
          },
          "categoryLabels": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "media": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductMedia"
            }
          },
          "locations": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/RedemptionLocation"
            }
          },
          "options": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/ProductOption"
            }
          }
        },
        "required": [
          "id",
          "title",
          "shortDescription",
          "description",
          "status",
          "availabilityRequired",
          "categoryLabels",
          "media",
          "locations",
          "options"
        ],
        "description": "A Groupon deal."
      },
      "ProductMedia": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string"
          },
          "role": {
            "type": "string",
            "description": "A size name: small, medium, large, extra_large or wide_crop. Not every size is present."
          },
          "width": {
            "type": "number",
            "nullable": true
          },
          "height": {
            "type": "number",
            "nullable": true
          }
        },
        "required": [
          "url",
          "role",
          "width",
          "height"
        ],
        "description": "One picture of a deal. Every entry is the same picture at another size."
      },
      "ProductOption": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "description": "The `optionId` of a cart line, and the `itemId` in cart item paths."
          },
          "title": {
            "type": "string"
          },
          "isDefault": {
            "type": "boolean"
          },
          "active": {
            "type": "boolean",
            "nullable": true,
            "description": "false is not sellable; null means Groupon does not know: treat it as sellable."
          },
          "minUnits": {
            "type": "number"
          },
          "maxUnits": {
            "type": "number",
            "nullable": true,
            "description": "null means no maximum."
          },
          "price": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Price"
              }
            ],
            "nullable": true,
            "description": "null when Groupon published no price for the option."
          },
          "promotion": {
            "allOf": [
              {
                "$ref": "#/components/schemas/Promotion"
              }
            ],
            "nullable": true
          },
          "selections": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/OptionSelection"
            }
          }
        },
        "required": [
          "id",
          "title",
          "isDefault",
          "active",
          "minUnits",
          "maxUnits",
          "price",
          "promotion",
          "selections"
        ],
        "description": "One purchasable variant of a deal, such as \"One 60-Minute Massage\"."
      },
      "Promotion": {
        "type": "object",
        "properties": {
          "amount": {
            "type": "number",
            "description": "The promotional per-unit price, in the same minor units and currency as `price.retail`."
          },
          "promoCode": {
            "type": "string",
            "nullable": true
          },
          "endsAt": {
            "type": "string",
            "nullable": true,
            "description": "When the promotion stops working; null when unknown."
          }
        },
        "required": [
          "amount",
          "promoCode",
          "endsAt"
        ],
        "description": "A promotional price a shopper gets with a code on Groupon's checkout page. Informational."
      },
      "RedemptionLocation": {
        "type": "object",
        "properties": {
          "id": {
            "type": "string",
            "nullable": true
          },
          "name": {
            "type": "string",
            "nullable": true
          },
          "street": {
            "type": "string",
            "nullable": true
          },
          "city": {
            "type": "string",
            "nullable": true
          },
          "state": {
            "type": "string",
            "nullable": true,
            "description": "Full state name, such as Illinois."
          },
          "postalCode": {
            "type": "string",
            "nullable": true
          },
          "country": {
            "type": "string",
            "nullable": true
          },
          "latitude": {
            "type": "number",
            "nullable": true
          },
          "longitude": {
            "type": "number",
            "nullable": true
          }
        },
        "required": [
          "id",
          "name",
          "street",
          "city",
          "state",
          "postalCode",
          "country",
          "latitude",
          "longitude"
        ],
        "description": "Where a voucher is redeemed. Any field can be unknown."
      },
      "StorefrontRegistration": {
        "type": "object",
        "properties": {
          "storefrontId": {
            "type": "string"
          },
          "partnerId": {
            "type": "string",
            "description": "Groupon's partner id: quote it to support."
          },
          "displayName": {
            "type": "string"
          },
          "contactName": {
            "type": "string"
          },
          "contactEmail": {
            "type": "string"
          },
          "logoUrl": {
            "type": "string",
            "nullable": true
          },
          "redirectUrl": {
            "type": "string",
            "nullable": true
          },
          "inventoryCountries": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "inventoryStates": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "category0": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "category1": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "category2": {
            "type": "array",
            "items": {
              "type": "string"
            }
          },
          "maxPageSize": {
            "type": "number",
            "nullable": true,
            "description": "The most products one page returns to this storefront; null for the default."
          },
          "cjPublisherId": {
            "type": "string",
            "nullable": true,
            "description": "The CJ publisher id that turns `buyLink` into an affiliate link; null without CJ."
          },
          "status": {
            "type": "string",
            "description": "Known values: active, deactivated."
          }
        },
        "required": [
          "storefrontId",
          "partnerId",
          "displayName",
          "contactName",
          "contactEmail",
          "logoUrl",
          "redirectUrl",
          "inventoryCountries",
          "inventoryStates",
          "category0",
          "category1",
          "category2",
          "maxPageSize",
          "cjPublisherId",
          "status"
        ],
        "description": "The storefront's registration as Groupon holds it now."
      },
      "CartCreateRequestBody": {
        "type": "object",
        "properties": {
          "country": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2. Only `US` today."
          },
          "clientReference": {
            "type": "string",
            "description": "Your own reference for the cart, echoed back."
          },
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CartItemInput"
            },
            "description": "1 to 20 lines."
          }
        },
        "required": [
          "country",
          "items"
        ]
      },
      "CartItemUpdateRequestBody": {
        "type": "object",
        "properties": {
          "quantity": {
            "type": "number",
            "description": "The new absolute quantity, 1 to 100. Remove the line instead of sending 0."
          },
          "expectedPrice": {
            "type": "number",
            "description": "The per-unit retail your site shows, in minor units."
          }
        },
        "required": [
          "quantity"
        ]
      },
      "CartItemsAddRequestBody": {
        "type": "object",
        "properties": {
          "items": {
            "type": "array",
            "items": {
              "$ref": "#/components/schemas/CartItemInput"
            },
            "description": "1 to 20 lines."
          }
        },
        "required": [
          "items"
        ]
      },
      "APIErrorResponse": {
        "type": "object",
        "description": "The body of every error response.",
        "properties": {
          "code": {
            "type": "string",
            "enum": [
              "canceled",
              "unknown",
              "invalid_argument",
              "deadline_exceeded",
              "not_found",
              "already_exists",
              "permission_denied",
              "resource_exhausted",
              "failed_precondition",
              "aborted",
              "out_of_range",
              "unimplemented",
              "internal",
              "unavailable",
              "data_loss",
              "unauthenticated"
            ],
            "description": "The error code in its wire form: an operation's errors name `notFound`, the body carries `not_found`."
          },
          "message": {
            "type": "string",
            "description": "What went wrong, in words."
          },
          "details": {
            "type": "object",
            "description": "Structured detail, on the errors that carry any."
          }
        },
        "required": [
          "code",
          "message"
        ]
      }
    },
    "securitySchemes": {
      "Authorization": {
        "type": "apiKey",
        "in": "header",
        "name": "authorization",
        "description": "`Bearer <token>`: a session token, or an API key (`grpn_...`)."
      }
    },
    "responses": {
      "APIError": {
        "description": "Error response",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/APIErrorResponse"
            }
          }
        }
      }
    }
  }
}
