Dinlr Online Order API

1. Authorization

The Dinlr Online Order API allows authorization using the OAuth 2.0 standard. Currently, we only support the Authorization Code Grant.

1.1 OAuth 2.0

Before starting, create a Dinlr application. To do this follow the steps below:

Step 1. Register as a Partner

If you have not done this yet, register a partner account here: https://partners.dinlr.com

Step 2. Create a Dinlr Application

Once you sign in you can click on "Apps" located at the side menu, which will show you a list of your Applications. Now you are ready to create your first app.

As a result, this process will give you the client_id and the client_secret which are used to identify your applications and are therefore, required to complete the authorization process.

redirect_uri is the URL where you want to redirect the users after they authorize the client.

1.2 Connecting your application to a Dinlr Account

Implement the following steps to connect your application to a Dinlr account.

Step 1. Requesting Authorization Code

The restaurant needs to authorize your application to access their data. Send them the following URL so that they can authorize your application


https://backoffice.dinlr.com/oauth/authorize?client_id={client_id}&redirect_uri={redirect_uri}&state={state}

The redirect_uri must be identical to one of the Application Redirect URI.

Once the restaurant has authorized the application, Dinlr will send an authorization code and the restaurant id to the Redirect URI you set up with your application.


Successful Authorization Response
{redirect_uri}?code={code}&restaurant_id={restaurant_id}&state={state}

Declined Access Response
{redirect_uri}?error=access_denied

Before you proceed, make sure your application performs the following security checks. If any of the checks fails, your application must reject the request with an error, and must not proceed further.

  • Ensure the provided state is the same one that your application provided to Dinlr during Step 1. Requesting Authorization Code.

If all security check pass, the authorization code can be exchanged once for an access and a refresh token.

Step 2. Requesting an Access and a Refresh Token

Once you have the authorization code, your application can now request an access token and a refresh token.

The following data should be sent as "application/x-www-form-urlencoded" encoded body of a POST request.


POST Request
https://api.dinlr.com/v1/{restaurant_id}/oauth/token

Parameters
  • code
  • client_id
  • client_secret
  • grant_type - this is always authorization_code

Response
{
    "access_token": "{access_token}",
    "token_type": "bearer",
    "expires_in": 1209600,
    "refresh_token": "{refresh_token}"
}

Step 3. Using Access Token to access Dinlr Online Order API

Your application can use the received access token to interact with the Dinlr API on behalf of the restaurant by providing the access token in an Authorization header.


GET Request
https://api.dinlr.com/v1/{restaurant_id}/onlineorder/get-settings

Header
Authorization: Bearer {access_token}

Step 4. Refreshing the Access Token

When the access token expires, your application can request a new access token using the refresh token received in Step 2. Requesting an Access and a Refresh Token.


POST Request
https://api.dinlr.com/v1/{restaurant_id}/oauth/token

Parameters
  • refresh_token
  • client_id
  • client_secret
  • grant_type - when refreshing tokens it should be refresh_token

Response
{
    "access_token": "{access_token}",
    "token_type": "bearer",
    "expires_in": 1209600,
    "refresh_token": "{refresh_token}"
}

2. Restaurant Settings

This should be the first request that you issue to the Dinlr server which provide information about the restaurant configuration.


GET Request
https://api.dinlr.com/v1/{restaurant_id}/onlineorder/get-settings

Header
Authorization: Bearer {access_token}

Response
{
    "data": {
        "locations": [
            {
                "id": "{location_id}",
                "name": "Chinatown"
            },
            {
                "id": "{location_id}",
                "name": "New York"
            }
        ],
        "dining_options": [
            {
                "id": "{dining_option_id}",
                "name": "Dine-in",
                "sort": 0
            },
            {
                "id": "{dining_option_id}",
                "name": "Takeaway",
                "sort": 1
            },
            {
                "id": "{dining_option_id}",
                "name": "Delivery",
                "sort": 2
            }
        ],
        "payments": [
            {
                "id": "{payment_id}",
                "name": "Cash",
                "sort": 0
            },
            {
                "id": "{payment_id}",
                "name": "Visa",
                "sort": 1
            },
            {
                "id": "{payment_id}",
                "name": "Mastercard",
                "sort": 2
            }
        ],
        "categories": [
            {
                "id": "{category_id}",
                "name": "Burgers"
            },
            {
                "id": "{category_id}",
                "name": "Salads"
            }
        ]
    }
}

3. Online Menu

This option return an entire online menu, including the items and modifiers.


GET Request
https://api.dinlr.com/v1/{restaurant_id}/onlineorder/menu?location_id={location_id}

Header
Authorization: Bearer {access_token}

Response
{
    "data": {
        "menus": [
            {
                "id": "{menu_id}",
                "name": "All-Day Promotion Menu",
                "sort": 0,
                "items": [
                    {
                        "id": "{item_id}",
                        "name": "Chargrilled Chicken Burger",
                        "description": "Grilled chicken with BBQ sauce", - optional
                        "sort": 0,
                        "image": "https://cdn.dinlr.com/......jpg", - optional
                        "category": "{category_id}",
                        "updated_at": "2018-03-08T13:00:00+08:00",
                        "variants": [
                            {
                                "id": "{variant_id}",
                                "name": "Regular",
                                "price": 9.5,
                                "sort": 0
                            },
                            {
                                "id": "{variant_id}",
                                "name": "Large",
                                "price": 12.5,
                                "sort": 1
                            },
                            {
                                "id": "{variant_id}",
                                "name": "Open Price",
                                "sort": 2
                            }
                        ],
                        "modifiers": [
                            {
                                "id": "{modifier_id}",
                                "name": "Sides",
                                "min_selection": 2, - null represents optional
                                "max_selection": 2, - null represents unlimited
                                "sort": 0,
                                "modifier_options": [
                                    {
                                        "id": "{modifier_option_id}",
                                        "name": "French Fries",
                                        "price": 0,
                                        "sort": 0
                                    },
                                    {
                                        "id": "{modifier_option_id}",
                                        "name": "Onion Rings",
                                        "price": 0.5,
                                        "sort": 1
                                    }
                                ]
                            }
                        ]
                    },
                    {
                        "id": "{item_id}",
                        "name": "Cheesecake",
                        "description": null,
                        "sort": 1,
                        "image": null,
                        "category": "{category_id}",
                        "updated_at": "2018-03-08T13:00:00+08:00",
                        "variants": [
                            {
                                "id": "{variant_id}",
                                "name": "Blueberry",
                                "price": 3.5,
                                "sort": 0
                            },
                            {
                                "id": "{variant_id}",
                                "name": "Oreo",
                                "price": 4.5,
                                "sort": 1
                            }
                        ],
                        "modifiers": [
                        ]
                    }
                ],
                "times": [
                    {
                        "day": Monday,
                        "start_time": "11:00",
                        "end_time": "22:00"
                    },
                    {
                        "day": Tuesday,
                        "start_time": "11:00",
                        "end_time": "22:00"
                    },
                    {
                        "day": Wednesday,
                        "start_time": "11:00",
                        "end_time": "22:00"
                    },
                    {
                        "day": Thursday,
                        "start_time": "11:00",
                        "end_time": "22:00"
                    },
                    {
                        "day": Friday,
                        "start_time": "11:00",
                        "end_time": "23:30"
                    },
                    {
                        "day": "Saturday",
                        "start_time": "11:00",
                        "end_time": "23:30"
                    },
                    {
                        "day": Sunday,
                        "start_time": "11:00",
                        "end_time": "23:30"
                    }
                ]
            }
        ]
    }
}

4. Items & Discounts

4.1 Retrieve all Items

Unlike the online menu option which only return the online menu and the items contained within each menu, this option return every items in the database.


GET Request
https://api.dinlr.com/v1/{restaurant_id}/onlineorder/items?location_id={location_id}

URL Parameters
  • location_id
  • limit - Return up to this many results per page (default: 50) (max: 250)
  • page - Return a specific page of results (default: 1)
  • update_at_min - Show items last updated after date (Remember to escape + sign with %2B, because + is not allowed to be used in URL)

Header
Authorization: Bearer {access_token}

Response
{
    "data": [
        {
            "id": "{item_id}",
            "name": "Chargrilled Chicken Burger",
            "description": "Grilled chicken with BBQ sauce", - optional
            "image": "https://cdn.dinlr.com/......jpg", - optional
            "category": "{category_id}",
            "updated_at": "2018-03-08T13:00:00+08:00",
            "variants": [
                {
                    "id": "{variant_id}",
                    "name": "Regular",
                    "price": 9.5,
                    "sort": 0
                },
                {
                    "id": "{variant_id}",
                    "name": "Large",
                    "price": 12.5,
                    "sort": 1
                },
                {
                    "id": "{variant_id}",
                    "name": "Open Price",
                    "sort": 2
                }
            ],
            "modifiers": [
                {
                    "id": "{modifier_id}",
                    "name": "Sides",
                    "min_selection": 2, - null represents optional
                    "max_selection": 2, - null represents unlimited
                    "sort": 0,
                    "modifier_options": [
                        {
                            "id": "{modifier_option_id}",
                            "name": "French Fries",
                            "price": 0,
                            "sort": 0
                        },
                        {
                            "id": "{modifier_option_id}",
                            "name": "Onion Rings",
                            "price": 0.5,
                            "sort": 1
                        }
                    ]
                }
            ]
        },
        {
            "id": "{item_id}",
            "name": "Cheesecake",
            "description": null,
            "image": null,
            "category": "{category_id}",
            "updated_at": "2018-03-08T13:00:00+08:00",
            "variants": [
                {
                    "id": "{variant_id}",
                    "name": "Blueberry",
                    "price": 3.5,
                    "sort": 0
                },
                {
                    "id": "{variant_id}",
                    "name": Oreo,
                    "price": 4.5,
                    "sort": 1
                }
            ],
            "modifiers": [
            ]
        }
    ]
}

4.2 Retrieve all Discounts

Retrieve every discounts in the database.


GET Request
https://api.dinlr.com/v1/{restaurant_id}/onlineorder/discounts?location_id={location_id}

URL Parameters
  • location_id
  • limit - Return up to this many results per page (default: 50) (max: 250)
  • page - Return a specific page of results (default: 1)
  • update_at_min - Show discounts last updated after date (Remember to escape + sign with %2B, because + is not allowed to be used in URL)

Header
Authorization: Bearer {access_token}

Response
{
    "data": [
        {
            "id": "{discount_id}",
            "name": "Staff Discount",
            "type": "percent", - Can be either "percent" or "price" discount
            "manufacturer_discount": true, - Manufacturer discount will be applied after charges and taxes
            "value": 10, - Since discount type is percent, it is 10% discount. If value is null, it means it is an open discount and value can be custom defined.
            "updated_at": "2018-03-08T13:00:00+08:00"
        },
        {
            "id": "{discount_id}",
            "name": "First-Timer Discount",
            "type": "price",
            "manufacturer_discount": true,
            "value": 15, - Since discount type is price, it is a $15 discount
            "updated_at": "2018-03-08T13:00:00+08:00"
        },
        {
            "id": "{discount_id}",
            "name": "Open Discount",
            "type": "price",
            "manufacturer_discount": false,
            "value": null, - Open discount, value can be defined later during 5.1 Cart Summary, 5.2 Place Order or 6.3 Update Order
            "updated_at": "2018-03-08T13:00:00+08:00"
        }
    ]
}

5. Place Order

5.1 Cart Summary

Calculate the total order cost by inputting an array of order items (products, modifier options and discounts identified by id) with their quantities and order information (dining option, order no, order ticket, pax and notes).


POST Request
https://api.dinlr.com/v1/{restaurant_id}/onlineorder/cart/calculate

Header
Authorization: Bearer {access_token}

Parameters
{
    "location": "{location_id}",
    "items": [
        {
            "item": "{item_id}",
            "qty": 2,
            "notes": "Add Jalapeno", - optional, max 200 characters
            "variant": "{variant_id}",
            "price": "99.99", - optional, only include this variable for open price variant, only works on variant with no defined value
            "modifier_options": [
                {
                    "modifier_option": "{modifier_option_id}"
                },
                {
                    "modifier_option": "{modifier_option_id}"
                }
            ],
            "discounts": [ - Item-based discount
                {
                    "discount": "{discount_id}",
                    "value": 10 - optional, only include this variable for open discount, only works on discount with no defined value
                },
                {
                    "discount": "{discount_id}"
                }
            ]
        },
        {
            "item": "{item_id}",
            "qty": 1,
            "variant": "{variant_id}"
        }
    ],
    "discounts": [ - Order wide discount
        {
            "discount": "{discount_id}",
            "value": 10, - optional, only include this variable for open discount, only works on discount with no defined value
        },
        {
            "discount": "{discount_id}"
        }
    ],
    "payments": [
        {
            "payment": "{payment_id}",
            "receipt_no": "BC928K", - optional, alphanumeric, no spaces, max 10 characters, unique but can use current order no
            "amount": 25.55
        }
    ],
    "order_info": {
        "dining_option": "{dining_option_id}",
        "order_no": "BC928K", - optional, alphanumeric, no spaces, max 10 characters, unique
        "order_ticket": "C23", - optional, max 50 characters
        "pax": 3, - optional, default 1
        "notes": "Self-collect at 3.30pm later" - optional, max 200 characters
    }
}

Response
{
    "data": {
        "subtotal": 15.54,
        "total": 10.54,
        "financial_status": "paid", - Can be either "pending", "partially_paid", "paid", "partially_refunded", "refunded" or "voided"
        "items": [
            {
                "item": "{item_id}",
                "price_per": 10.3,
                "qty": 2,
                "price": 20.6,
                "variant": "{variant_id}",
                "variant_price": 9.5,
                "sort": 0,
                "modifier_options": [
                    {
                        "modifier_option": "{modifier_option_id}",
                        "price": 0.5
                    },
                    {
                        "modifier_option": "{modifier_option_id}",
                        "price": 0.3
                    }
                ],
                "discounts": [
                    {
                        "discount": "{discount_id}",
                        "amount": 2.06
                    },
                    {
                        "discount": "{discount_id}",
                        "amount": 1
                    }
                ]
            },
            {
                "item": "{item_id}",
                "price_per": 10,
                "qty": 1,
                "price": 10,
                "variant": "{variant_id}",
                "variant_price": 10,
                "sort": 1,
                "modifier_options": [
                ],
                "discounts": [
                ]
            }
        ],
        "discounts": [
            {
                "discount": "{discount_id}",
                "amount": 10,
            },
            {
                "discount": "{discount_id}",
                "amount": 2,
            }
        ],
        "charges": [
            {
                "charge": "{charge_id}",
                "amount": 8,
                "name": "Delivery Fee"
            }
        ],
        "taxes": [
            {
                "tax": "{tax_id}",
                "amount": 2,
                "name": "Government Tax",
                "inclusive": false
            }
        ],
        "manufacturer_discounts": [
            {
                "discount": "{discount_id}",
                "amount": 5,
            },
            {
                "discount": "{discount_id}",
                "amount": 10,
            }
        ],
        "payments": [
            {
                "payment": "{payment _id}",
                "receipt_no": "BC928K",
                "amount": 10.55
            }
        ]
    }
}

5.2 Place Order

The parameters is similar to cart summary, but this option will place an order to the database. Once order has been placed, the default order status will be "pending". When the front-line staff accepts the order, the status will change to either "open" or "closed", or when they reject the order, the status will change to "cancelled" and all payment & refund for the order will be removed.


POST Request
https://api.dinlr.com/v1/{restaurant_id}/onlineorder/cart/submit

Header
Authorization: Bearer {access_token}

Parameters
Same parameters as 5.1 Cart Summary

Response
Same response as 6.2 View Order

6. Manage Order

6.1 List Order

Retrieve orders placed by your Application.


GET Request
https://api.dinlr.com/v1/{restaurant_id}/onlineorder/orders?location_id={location_id}

Header
Authorization: Bearer {access_token}

URL Parameters
  • location_id
  • limit - Return up to this many results per page (default: 50) (max: 250)
  • page - Return a specific page of results (default: 1)
  • update_at_min - Show orders last updated after date (Remember to escape + sign with %2B, because + is not allowed to be used in URL)

Response
{
    "data": [
        {
            "id": "{order_id}",
            "order_no": "BC928K",
            "order_ticket": "C23",
            "updated_at": "2018-03-08T13:00:00+08:00",
            "created_at": "2018-03-08T13:00:00+08:00",
            "total": "79.06",
            "subtotal": "71.42",
            "status": "open", - Can be either "pending", "open", "closed" or "cancelled"
            "financial_status": "paid", - Can be either "pending", "partially_paid", "paid", "partially_refunded", "refunded" or "voided"
            "kitchen_status": null, - Can be either null, "fulfilled" or "partial"
            "expedite_status": null, - Can be either null, "expedited" or "partial"
        },
        {
            "id": "{order_id}",
            "order_no": "AF920F",
            "order_ticket": "C22",
            "updated_at": "2018-03-08T13:00:00+08:00",
            "created_at": "2018-03-08T13:00:00+08:00",
            "total": "89.99",
            "subtotal": "87.99",
            "status": "closed",
            "financial_status": "pending",
            "kitchen_status": "fulfilled",
            "expedite_status": "partial"
        }
    ]
}

6.2 View Order

View an order details (Items, discounts, taxes, charges and summary) identified by id


GET Request
https://api.dinlr.com/v1/{restaurant_id}/onlineorder/orders/{order_id}

Header
Authorization: Bearer {access_token}

Response
{
    "data": {
        "id": "{order_id}",
        "order_no": "BC928K",
        "order_ticket": "C23",
        "dining_option": "{dining_option_id}",
        "pax":4,
        "subtotal": 6.42,
        "total": 2.55,
        "status": "open", - Can be either "pending", "open", "closed" or "cancelled"
        "financial_status": "partially_refunded", - Can be either "pending", "partially_paid", "paid", "partially_refunded", "refunded" or "voided"
        "kitchen_status": null, - Can be either null, "fulfilled" or "partial"
        "expedite_status": null, - Can be either null, "expedited" or "partial"
        "notes": null, - optional, max 200 characters
        "updated_at": "2018-03-08T13:00:00+08:00",
        "created_at": "2018-03-08T13:00:00+08:00",
        "items": [
            {
                "id": "{order_item_id}",
                "item": "{item_id}",
                "price_per": 10.3,
                "qty": 2,
                "price": 20.6,
                "notes": null, - optional, max 200 characters
                "variant": "{variant_id}",
                "variant_price": 9.5,
                "sort": 0,
                "modifier_options": [
                    {
                        "modifier_option": "{modifier_option_id}",
                        "price": 0.5
                    },
                    {
                        "modifier_option": "{modifier_option_id}",
                        "price": 0.3
                    }
                ],
                "discounts": [
                    {
                        "discount": "{discount_id}",
                        "amount": 6.18
                    }
                ]
            }
        ],
        "discounts": [
            {
                "discount": "{discount_id}",
                "amount": 8
            }
        ],
        "charges": [
            {
                "charge": "{charge_id}",
                "amount": 0.64,
                "name": "Service Charge"
            }
        ],
        "taxes": [
            {
                "tax": "{tax_id}",
                "amount": 0.49,
                "name": "GST",
                "inclusive": false
            }
        ],
        "manufacturer_discounts": [
            {
                "discount": "{discount_id}",
                "amount": 5
            }
        ],
        "payments": [
            {
                "id": "{receipt_id}",
                "payment": "{payment_id}",
                "receipt_no": "BC928K",
                "amount": 2.55,
                "created_at": "2018-03-08T13:00:00+08:00"
            }
        ],
        "refunds": [
            {
                "id": "{refund_id}",
                "refund_no": "RFN069A",
                "amount": 0.55,
                "created_at": "2018-03-08T13:00:00+08:00"
            }
        ]
    }
}

6.3 Update Order

Update existing order items, discounts and payments.


PUT Request
https://api.dinlr.com/v1/{restaurant_id}/onlineorder/orders/{order_id}

Header
Authorization: Bearer {access_token}

Parameters
{
    "items": [
        {
            "id": "{order_item_id}", - *NOTE* Use order item id to retain the item’s kitchen and expedite status, or it will act as a new item
            "item": "{item_id}",
            "qty": 2,
            "notes": "Add Jalapeno", - optional, max 200 characters
            "variant": "{variant_id}",
            "price": "99.99", - optional, only include this variable for open price variant, only works on variant with no defined value
            "modifier_options": [
                {
                    "modifier_option": "{modifier_option_id}"
                }
            ],
            "discounts": [ - Item-based discount
                {
                    "discount": "{discount_id}",
                    "value": 10 - optional, only include this variable for open discount, only works on discount with no defined value
                },
                {
                    "discount": "{discount_id}"
                }
            ]
        },
        {
            "id": "{order_item_id}",
            "item": "{item_id}",
            "qty": 1,
            "variant": "{variant_id}"
        },
        { - Item with no id variable will act as a new item
            "item": "{item_id}",
            "qty": 1,
            "variant": "{variant_id}"
        }
    ],
    "discounts": [ - Order wide discount
        {
            "discount": "{discount _id}",
            "value": 10, - optional, only include this variable for open discount, only works on discount with no defined value
        },
        {
            "discount": "{discount _id}"
        }
     ],
    "payments": [ - *NOTE* ONLY include new payment, DO NOT INCLUDE existing/previous payments, leave empty if there is no new payment (Reason: Dinlr does not allow amendment of payment once it is recorded)
        {
            "payment": "{payment_id}",
            "receipt_no": "BC928K", - optional, alphanumeric, no spaces, max 10 characters, unique but can use current order no
            "amount": 25.55
        }
    ],
    "order_info": {
        "dining_option": "{dining_option_id}",
        "order_no": "BC928K", - optional, alphanumeric, no spaces, max 10 characters, unique, leave empty to use previous order_no
        "order_ticket": "C23", - optional, max 50 characters, leave empty to use previous order_ticket
        "pax": 3, - optional, leave empty to use previous pax
        "notes": "Self-collect at 3.30pm later" - optional, max 200 characters
    }
}

Response
Same response as 6.2 View Order