External Discounts

For brands that use loyalty providers that are not integrated with PAR Ordering, our APIs allow for their discounts to be applied to a cart via secure machine-to-machine communication.

A Punchh brand does not use this page. Punchh rewards, offers, credits, and promo codes are applied through the Punchh guide. Sending them here as non_integrated skips Punchh.

Authentication

Because the discount amount is calculated outside PAR Ordering, the flow is designed to be driven server to server from your backend rather than from the customer's device, using a client_id and client_secret issued to you.

Generate Access Token

Exchange those credentials for an access token at /api/oauth/tokens. The credentials go in an Authorization: Basic header as base64(client_id:client_secret); the body carries grant_type and the scope you need.

Where this token applies. It authenticates the server-to-server Ordering API calls that accept it — order creation and calculation carry the OAuth scope check. The Cart 2.0 calls shown below are authenticated the ordinary way, with the Application key and the customer's Authorization token, and do not read a bearer token. Keep the discount calculation on your backend regardless: a discount amount is accepted as sent.

Request

Attribute Type Example Value Description
Application Header Application Key "f3a90488ffee32c3acb6fcd0ca417cf6" Specific Management Center application key provided by PAR Ordering
Authorization Header "Basic 32c3acb6fcd0ca417cf6f3a90488ffee" Basic Authorization header is based on the previously received client_id and client_secret and is generated as follows : base_64_encode(client_id:client_secret)
scope string "order" Token access scope
{
  "method": "post",
  "url": "https://api-public-demo.menu.app/api/oauth/tokens",
  "headers": {
    "X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
    "Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
    "Authorization": "Basic 32c3acb6fcd0ca417cf6f3a90488ffee",
    "Content-Type": "application/x-www-form-urlencoded",
    "Api-Version": "4.78.0",
    "X-Role-ID": ""
  },
  "body":{
    "grant_type": "client_credentials",
    "scope": "order"
}
}

Response

{
    "status": "OK",
    "code": 200,
    "data": {
        "oauth_token": {
            "access_token": "d4c129d3f4560c2beaa3a1a3b15bb771a7038a4bbb680a3912c9ea284d07b291",
            "token_type": "bearer",
            "scope": "order",
            "expires_in": 86399
        }
    }
}
Attribute Type Example Value Description
oauth_token.access_token string "f3a90488ffee32c3acb6fcd0ca417cf6" Access token for the future creation and editing of the webhooks configurations. This token should be used as Bearer token in the next calls.
oauth_token.expires_in int "86399" Token expiration time in seconds
oauth_token.scope string "order" Token access scope

Applying the discount to the cart

There is no separate calculation call. Put the discount on the cart with Update Cart, marking its origin as non-integrated, and the response returns the recalculated totals in summary.

Request

Attribute Type Example Value Description
metadata.venue_id string "4fac4dfc-3d0e-4b9f-8081-8448be89013b" Venue UUID
metadata.order_type.id int 6 Type ID of order type for which order should be placed - see Order Types reference
cart.products array The products in the basket - see Server Side Cart for the full product shape
cart.discounts.discount_amount int 500 The amount of money to be deducted from the subtotal, in minor currency units.
cart.discounts.origin_type string "non_integrated" The origin of the discount. Use non_integrated for a loyalty provider that is not integrated with PAR Ordering. The other accepted values are integrated and manager_discount.
cart.discounts.type_id int 2 What kind of discount it is - 1 coupon, 2 loyalty reward, 3 promotion, 4 credit, 5 promo code.
cart.discounts.name string "Loyalty reward" Optional label shown to the customer.
{
  "method": "put",
  "url": "https://api-public-demo.menu.app/api/cart/f6ce31f7b7549cc7c3e5326661cf1dc3b5ea5c3fd89cce634667e483e23fb51a",
  "headers": {
    "X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
    "Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
    "Api-Version": "4.78.0",
    "Content-Type": "application/json"
  },
  "body": {
    "metadata": {
      "venue_id": "4fac4dfc-3d0e-4b9f-8081-8448be89013b",
      "order_type": {
        "id": 6,
        "pickup_asap": true
      }
    },
    "cart": {
      "products": [
        {
          "price_id": "76efaa5d-b849-4549-9468-72b8131b904a",
          "quantity": 1,
          "comment": null,
          "product_groups": []
        }
      ],
      "discounts": [
        {
          "type_id": 2,
          "discount_amount": 500,
          "origin_type": "non_integrated",
          "name": "Loyalty reward"
        }
      ],
      "tip": {
        "amount": 0,
        "type": 1
      }
    }
  }
}

Every cart update re-prices the basket, so read the discounted totals from summary in the response. When the customer is ready to pay, call POST /cart/{cart_id}/checkout, which re-prices against the POS with accurate tax before payment.

See Server Side Cart for the full cart flow.

Creating Order

Once payment initialization is called with the updated total cost, you can proceed with placing the order via POST /cart/{cart_id}/order:

Request

Attribute Type Example Value Description
customer_info object Contact details for the order
payment_info.payment_init_hash string "6d930b1593304c87f1092001ceb29ae2" The hash returned by POST /cart/{cart_id}/payments/init

The discount is already on the cart from the previous step, so it is not repeated here. The cart is the source of truth for items, discounts and totals.

{
  "method": "post",
  "url": "https://api-public-demo.menu.app/api/cart/f6ce31f7b7549cc7c3e5326661cf1dc3b5ea5c3fd89cce634667e483e23fb51a/order",
  "headers": {
    "X-Request-ID": "69da3547-204b-4093-a225-54e084c24215",
    "Application": "f3a90488ffee32c3acb6fcd0ca417cf6",
    "Api-Version": "4.78.0",
    "Content-Type": "application/json"
  },
  "body": {
      "customer_info": {
          "email": "jane.doe@partech.com",
          "first_name": "Jane",
          "last_name": "Doe",
          "phone_number": "+112345566"
      },
      "payment_info": {
          "payment_init_hash": "6d930b1593304c87f1092001ceb29ae2"
      }
  }
}

See Server Side Cart for the full checkout and order flow.

The taxes are calculated on the PAR Ordering and POS side. When the discount is applied, the discount amount is discounted proportionally from all the menu items and combos, as the taxes are different for different product types.