Skip to content

Bolt restaurant orders API

Introduction

This guide helps you get started with using the WYB Bolt restaurant orders REST API to place an order or retrieve one or multiple orders with their tracking information attached.

This API is meant to replace the initially used Google Sheet based synchronization method while keeping the main purpose intact, so data sent and retrieved is very similar to that method.

Authorization

The API uses Bearer Token authentication (or token authentication). Every request must include an Authorization header with the value of the provided token.
The header should follow the following pattern:
Authorization: Bearer <token>

For safety reasons, the API does not provide any details when a request authorization fails, except the 401 Unauthorized HTTP response code. Consider this response code as a missing or invalid token issue.

Every token is manually created for custom requests, and can be invalidated the same way.
A token can be associated with a user, and multiple tokens (users) can be issued to your company if necessary. This can help in keeping track of user actions.

For more help, please contact your WYB contact, who can forward your questions and requests to IT.

Rate limiting

The system uses rate limiting to prevent taking up resources; the current setup for this is 60 requests per minute. In the event of a violation of this limit, the system simply denies any further request until your quota is refreshed, and returns a 429 Too Many Requests response. The response is the following in this scenario:

{
"message": "You have made too many requests! See the documentation for more information."
}

Placing an order

You can place an order by sending a POST request to the /api/v2/order endpoint.

FieldDescriptionConstraintsExample
first_nameFirst name of the customer contactRequired
Max 255 characters
”John”
last_nameLast name of the customer contactRequired
Max 255 characters
”Doe”
consigneeName of partner company (formerly known as “Restaurant Name”)Required
Max 255 characters
”John D’s”
emailEmail address of the customer contactRequired
Max 255 characters
RFC2822 compliant
john@doe.test
phonePhone number of the customer contactRequired
Max 255 characters
”303058100”
zipZIP (postal) code of the customer delivery addressRequired
Max 255 characters
”2810-432”
cityCity of the customer delivery addressRequired
Max 255 characters
”Lisbon”
streetStreet name of the customer delivery addressRequired
Max 255 characters
”Rua de Jane Doe”
house_numberHouse number of the customer delivery addressRequired
Max 255 characters
”12”
floorFloor number/label of the customer delivery addressOptional
Max 255 characters
”4”
doorDoor number/label of the customer delivery addressOptional
Max 255 characters
”B”
opening_hoursOpening hours of the customer (consignee)Optional
Max 255 characters
”08.30-17.30 Mon-Fri”
product_idID of the product for this orderRequired
Existing Product ID
8
product_variation_idID of the desired variation for the product of this orderRequired if the product has variations
Existing Product Variation ID
3
loginLogin credential for the restaurant deviceRequired
Max 255 characters
”So7V8FcniY”
passwordPassword credential for the restaurant deviceRequired
Max 255 characters
”F90uFLbKas”
order_typeType of the order - See constraints for possible valuesRequired
Enum: REGULAR, RETURN, EXCHANGE
”REGULAR”
original_order_idID of the original order that is being returned/exchangedOptional
Existing Order ID
”1234”
testWhether the order is a test - this stop the order from being processedOptional
Boolean
1
noteA comment specific to the address associated with the order.Optional
String
”Leave package at door”

Disclaimer: Please never use the above example values for your production request, as they are publicly visible to everyone.

Example request

{
"first_name": "John",
"last_name": "Doe",
"consignee": "John D's",
"email": "john@doe.test",
"phone": "303058100",
"country": "pt",
"zip": "2810-432",
"city": "Lisbon",
"street": "Rua de Jane Doe",
"house_number": "12",
"opening_hours": "08.30-17.30 Mon-Fri",
"product_id": 8,
"login": "So7V8FcniY",
"password": "F90uFLbKas",
"order_type": "REGULAR",
"note": "Leave package at door"
}

Example responses

On success

201 Created

{
"message": "Order successfully placed.",
"orders": [
{
"order_id": "1234",
"order_ref": "BOLTPTREST1234",
"order_type": "REGULAR"
}
]
}

On failure

400 Bad Request

{
"message": "Bad request."
}

Order Types

To determine the type of an Order, the system uses OrderType enums. These are the following:

NameValueDescription
REGULAR1Used for regular door to door order placement
EXCHANGE2Used for sending out and exchange product that was initially sent as a REGULAR order
RETURN3Used for placing a return order for retrieving the fauly/warrantied/exchanged products

Retrieving multiple orders

You can retrieve one or multiple orders by sending a GET request to the /api/v2/order endpoint.
The results are always paginated, allowing a maximum of 25 results per page.

You can use any of the following filter fileds in any combination:

FieldDescriptionConstraintsExample
order_idMarket specific order ID. This is the ID you receive back when placing and order”1234”
created_fromOnly shows orders placed starting from this date timeISO8601 compliant”2024-01-01T12:00:00”
created_toOnly shows orders placed until this date timeISO8601 compliant”2024-01-07”
tracking_numberThe package tracking number/code provided by the fulfilment partner”1248JF83LRO2”
deliveredThe order is considered delivered or notBoolean valuetrue or false
delivered_fromOnly shows orders delivered starting from this date timeISO8601 compliant”2024-01-14T00:00:00”
delivered_toOnly shows orders delivered until this date timeISO8601 compliant”2024-01-16T12:00:00”
order_typeThe type of the order - See constraints for possible valuesEnum: REGULAR, RETURN, EXCHANGE”REGULAR”

Example request

{
"created_from": "2024-01-01",
"created_to": "2024-01-02",
"order_type": "REGULAR"
}

The example above is a request that queries for all orders that are:

  • created staring from the 1st of January 2024
  • created until the 2nd of January 2024
  • regular orders

Example responses

On success

GET https://domain.test/api/v2/orders?created_from=2024-01-01&created_to=2024-01-02&order_type=REGULAR

200 OK

{
"data": [
{
"order_id": 1234,
"order_ref": "BOLTPTREST1234",
"created_at": "2024-02-01T13:31",
"first_name": "John",
"last_name": "Doe",
"consignee": "John D's",
"email": "john@doe.test",
"phone": "303058100",
"zip": "2810-432",
"city": "Lisbon",
"street": "Rua de Jane Doe",
"house_number": "12",
"floor": null,
"door": "12",
"opening_hours": "08.30-17.30 Mon-Fri",
"product_id": 8,
"product_variation_id": null,
"login": "So7V8FcniY",
"password": "F90uFLbKas",
"final_completion_date": null,
"order_type": "REGULAR",
"original_order_id": null,
"trackings": [
{
"status_date": "2024-02-02T03:10",
"status": "Arrival at operations centre.",
"dispatch_date": "2024-02-02T00:49",
"delivery_date": null,
"tracking_number": "EXAMPLE-TRACKING-NUMBER",
"tracking_link": "https://courier.test/track/EXAMPLE-TRACKING-NUMBER"
}
],
"detailed_status": {
"status_date": "2024-02-02T03:10",
"status": "Transit",
"location": "Example operations center",
"description": "Your parcel is in our premises",
"tracking_number": "EXAMPLE-TRACKING-NUMBER",
"tracking_link": "https://tracking-aggregator.test/track/EXAMPLE-TRACKING-NUMBER"
}
"serial_number": "SERIAL-NUMBER-1234",
"delivery_errors": [
{
"status": "Recipient not available",
"date": "2024-02-02T15:25",
"comment": null
}
],
"bolt_comments" : []
}
],
"links": {
"first": "https://domain.test/api/v2/order?created_from=2024-02-01&created_to=2024-02-02&page=1",
"last": null,
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"path": "https://domain.test/api/v2/order",
"per_page": 15,
"to": 1
}
}

On failure

GET https://domain.test/api/v2/orders?created_from=monday&order_type=

400 Bad Request

{
"message": "Bad request.",
"errors": {
"created_from": [
"The created from is not a valid date."
],
"order_type": [
"The order type must be a string.",
"The selected order type is invalid."
]
}
}

Pagination

In the example above, you can notice that returning multiple orders also returns pagination-related metadata. The links object provides links for querying the first and last pages of the results
as well as the previous and next pages.

Retrieving a single order

In case you don’t want to bother with complex filters and pagination, you can just make a GET request to the api/v2/order/{id} endpoint, where the id is the ID of the order you’re looking for.

The returned order has the very same format, just like when retrieving multiple orders.

Example responses

On success

GET https://domain.test/api/v2/order/1234

200 OK

{
"order_id": 1234,
"order_ref": "BOLTPTREST1234",
"created_at": "2024-02-01T13:31",
"first_name": "John",
"last_name": "Doe",
"consignee": "John D's",
"email": "john@doe.test",
"phone": "303058100",
"zip": "2810-432",
"city": "Lisbon",
"street": "Rua de Jane Doe",
"house_number": "12",
"floor": null,
"door": "12",
"opening_hours": "08.30-17.30 Mon-Fri",
"product_id": 8,
"product_variation_id": null,
"login": "So7V8FcniY",
"password": "F90uFLbKas",
"final_completion_date": null,
"order_type": "REGULAR",
"original_order_id": null,
"trackings": [
{
"status_date": "2024-02-02T03:10",
"status": "Arrival at operations centre.",
"dispatch_date": "2024-02-02T00:49",
"delivery_date": null,
"tracking_number": "EXAMPLE-TRACKING-NUMBER",
"tracking_link": "https://courier.test/track/EXAMPLE-TRACKING-NUMBER"
}
],
"detailed_status": {
"status_date": "2024-02-02T03:10",
"status": "Transit",
"location": "Example operations center",
"description": "Your parcel is in our premises",
"tracking_number": "EXAMPLE-TRACKING-NUMBER",
"tracking_link": "https://tracking-aggregator.test/track/EXAMPLE-TRACKING-NUMBER"
}
"serial_number": "SERIAL-NUMBER-1234",
"delivery_errors": [
{
"status": "Recipient not available",
"date": "2024-02-02T15:25",
"comment": null
}
],
"comments": []
}

On failure

GET https://domain.test/api/v2/order/not-existing-order-id

404 Not Found

{
"message": "Order not found."
}

Listing Product and Product Variations

Product can be listed in a paginated manner by sending a GET request to the /api/v2/product endpoint. The response contains every detail needed during the order placement process.

Example response

GET https://domain.test/api/v2/product

200 OK

{
"data": [
{
"id": 8,
"name": "Jacket",
"variations": [
{
"id": 14,
"name": "S"
},
{
"id": 15,
"name": "M"
},
{
"id": 16,
"name": "L"
}
]
}
]
}

Datetime values

The system uses ISO8601 datetime values for both receiving and returning datetimes. They are built up in the following pattern:
YYYY-MM-DD'T'HH-MM-SS

Example:
2024-01-07T18:30:15 means the 7th of January 2024, 18:30:15 (6:30:15 PM).

The time (hour, minutes, seconds) part is omittable, and with this the character “T” is omittable as well. In this scenario, midnight (00:00:00) will be considered the time part.

Order Comment API

This endpoint is used to add or update a comment for an order identified by its unique id.

Endpoint URL

POST /api/v2/order/{id}/comment

Example request

{
"bolt_comment": "This is a new comment for the order."
}

Example response

{
"success": true
}

Error Response

{
"message": "Validation failed",
"errors": {
"bolt_comment": "The comment field is required."
}
}

Not Found Response

{
"success": false,
"message": "Order not found."
}

Order Update API

POST /api/v2/order/{id}/update

The Order Update API allows you to update all fields associated with an order, including all the details provided during order placement. This endpoint can be used to modify customer information, shipping address, or any other relevant data, as long as the order has not yet been sent to logistics.

Example request

POST /api/v2/order/5735/update

{
"first_name": "Jane",
"last_name": "Doe",
"product_id": "51"
}

Example response

{
"message": "Order successfully updated!",
"orders": [
{
"order_id": 5735,
"order_ref": "BOLTPT5735",
"order_type": "REGULAR"
}
]
}