Skip to content

OpenAPI Reference ​

Complete OpenAPI specification available for download:

Environments ​

EnvironmentURL
Productionhttps://prod.store-management.glovo.alb.app.onlineservice.io

Integration, including testing against test stores, runs against this endpoint. Test stores are allocated in the same environment and are distinguished by configuration, not by address.


POST /api/v3/menu/validate ​

The endpoint allows users to upload a menu and validate it according to the JSON schema. If no errors or warnings are detected, the endpoint will return an all-okay message. If errors or warnings are detected, the endpoint will return a list of errors and warnings, along with detailed information about each error (line number, column number, and error message).

RECOMMENDATION

Validate the payload before sending the menu for execution. This will ensure that the menu is in the correct format and will save time by identifying errors early.

Request Body: application/json — menu payload as JSON string

bash
curl -X POST \
  'https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/menu/validate' \
  -H 'Authorization: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "store_environment": "prod",
    "store_id": "partner__001",
    "partner_name": "partner",
    "super_categories": [...]
  }'
python
import requests

url = "https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/menu/validate"
headers = {
    "Authorization": "YOUR_API_KEY",
    "Content-Type": "application/json"
}
payload = {
    "store_environment": "prod",
    "store_id": "partner__001",
    "partner_name": "partner",
    "super_categories": [...]
}

response = requests.post(url, json=payload, headers=headers)
print(response.json())
javascript
const response = await fetch(
  'https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/menu/validate',
  {
    method: 'POST',
    headers: {
      'Authorization': 'YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      store_environment: 'prod',
      store_id: 'partner__001',
      partner_name: 'partner',
      super_categories: [...]
    })
  }
);
const data = await response.json();
java
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
    .uri(URI.create("https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/menu/validate"))
    .header("Authorization", "YOUR_API_KEY")
    .header("Content-Type", "application/json")
    .POST(HttpRequest.BodyPublishers.ofString(jsonPayload))
    .build();
HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());
php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/menu/validate');
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
    'Authorization: YOUR_API_KEY',
    'Content-Type: application/json'
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, $jsonPayload);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
go
req, _ := http.NewRequest("POST",
    "https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/menu/validate",
    bytes.NewBuffer(jsonPayload))
req.Header.Set("Authorization", "YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
resp, _ := http.DefaultClient.Do(req)

Responses:

StatusDescription
200Menu Validation Result
400The menu is not valid, or the request could not be read — the reason is in the body
500Internal error

Response Schema MenuValidationResponse:

json
{
  "valid": true,
  "errors": ["string"],
  "warnings": ["string"]
}
FieldTypeDescription
validbooleanSpecifies if the menu is valid or not
errorsarray[string]Detailed information of the errors generated by JSON schema
warningsarray[string]Detailed information of the warnings generated by JSON schema

Upload Menu V3 ​

POST /api/v3/menu/upload ​

This API endpoint allows users to upload or update the entire menu of a store in Glovo. The process is asynchronous — the endpoint returns a transaction_id that can be used to track the progress using the Check Status endpoint.

DAILY LIMIT

There is a maximum of 5 menu updates allowed per day per store address. If this limit is reached, the endpoint will return status code 429 (Too Many Requests). For small updates to products and attributes, it is recommended to use individual or bulk endpoints.

ATOMIC OPERATION

In the event that the Glovo system encounters an error while updating the menu, no changes will be made to avoid inconsistencies.

Request Body: application/json

json
{
  "store_id": "partner__001",
  "store_environment": "prod",
  "partner_name": "partner",
  "super_categories": [
    {
      "name": "default",
      "position": 0,
      "image_url": null,
      "display_super_category": false,
      "categories": [...]
    }
  ]
}
bash
curl -X POST \
  'https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/menu/upload' \
  -H 'Authorization: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d @menu.json
python
import requests

url = "https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/menu/upload"
headers = {"Authorization": "YOUR_API_KEY", "Content-Type": "application/json"}
response = requests.post(url, json=menu_payload, headers=headers)
print(response.json())

Responses:

StatusDescription
200Upload accepted — contains transaction_id
400Invalid request, unknown store, store not activated in Glovo, or menu refused by validation
429Daily limit exceeded — detail carries Glovo's reason
500Internal error — detail carries a reference to quote to integration support
502Glovo could not process the upload or could not be reached; retry later

Response Schema MenuUploadResponse:

json
{
  "status": "string",
  "transaction_id": "a946a2c7-f4e7-46ac-ae63-8a5497cb0ad9",
  "message": "string",
  "detail": "string"
}

transaction_id is returned only with 200. On any other status, message states what failed and detail states what to change — the field path, the value or the store concerned:

json
{
  "status": "ERROR",
  "transaction_id": null,
  "message": "The menu upload request is invalid",
  "detail": "Field 'super_categories[0].categories[1].sections[0].products[0].price' is not a number: '18,00'. Use a dot as the decimal separator, for example \"25.00\".",
  "validation": null
}

Schema MenuUpdateRequest ​

FieldTypeDescription
store_idstringThe unique identifier of the store
store_environmentstringThe environment of the store: prod or staging
partner_namestringThe name of the partner / POS solution
super_categorySuperCategoryA single super category (backward compatibility V2)
super_categoriesarray[SuperCategory]The list of super categories (V3 — recommended)

Schema SuperCategory ​

A "super-category" is the highest level of categorization in the Glovo menu.

FieldTypeDescription
namestringThe name of the super category
positionintegerThe position in the menu
image_urlstringImage URL (HTTPS required)
display_super_categorybooleanWhether the super category should be displayed
categoriesarray[Category]The list of categories

Schema Category ​

A category is a secondary level of organization in the Glovo menu. It is mandatory to have at least one category. A category is composed of sections and must have at least one section. Examples: beverages, burgers, salads, desserts, pasta.

FieldTypeDescription
namestringThe name of the category
positionintegerThe position of the category in the menu
image_urlstringThe URL of the category image (HTTPS)
sectionsarray[Section]The list of sections within the category

Schema Section ​

FieldTypeDescription
namestringThe name of the section
positionintegerThe position of the section
productsarray[Product]List of products belonging to this section

Schema Product ​

A product is a fundamental element of the Glovo menu, typically representing a physical item available in a store. However, the store has the freedom to decide what it wants to offer as products. Each product is associated with a section.

FieldTypeDescription
idstringThe ID of the product (must be unique)
namestringThe name of the product
pricestringThe price of the product
imageUrlstringThe URL of the main image (HTTPS required)
extraImageUrlsarray[string]Additional image URLs (HTTPS, max 9 images)
descriptionstringThe description of the product
availablebooleanWhether the product is available (default: true)
attribute_groupsarray[AttributeGroup]A list of attribute groups

Schema AttributeGroup ​

Attribute groups allow grouping similar customizations into generic sets, each of which can have a minimum and maximum number of options for the customer. For example: sauces (mayonnaise, mustard, ketchup) or beverages (water, cola, lemonade).

FieldTypeDescription
idstringThe ID of the group
namestringThe name of the group
minintegerThe minimum number of attributes that can be selected
maxintegerThe maximum number of attributes that can be selected
collapsebooleanWhether the group should be collapsed or expanded by default
attributesarray[Attribute]The list of attributes for this group
multiple_selectionbooleanWhether multiple attributes can be selected

Schema Attribute ​

Products can be customized in various ways, such as adding mayonnaise, including a beverage, or adding extra meat. Each of these customizations is known as an attribute. Products are not required to have attributes, but each attribute can have a different impact on the price.

FieldTypeDescription
idstringThe ID of the attribute (must be unique)
namestringThe name of the attribute
availablebooleanWhether the attribute is available (default: true)
selected_by_defaultbooleanWhether the attribute is selected by default (default: false)
pricestringThe price of the attribute (default: null)

Check Status V3 ​

GET /api/v3/menu/checkstatus/{trackingCode} ​

Check the status of the menu update process for a given transaction_id.

Parameters:

ParameterInTypeRequiredDescription
trackingCodepathstringYestransaction_id returned by upload
bash
curl -X GET \
  'https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/menu/checkstatus/a946a2c7-f4e7-46ac-ae63-8a5497cb0ad9' \
  -H 'Authorization: YOUR_API_KEY'
python
import requests

url = "https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/menu/checkstatus/a946a2c7-f4e7-46ac-ae63-8a5497cb0ad9"
response = requests.get(url, headers={"Authorization": "YOUR_API_KEY"})
print(response.json())

Response Schema MenuUploadStatus:

json
{
  "transaction_id": "a946a2c7-f4e7-46ac-ae63-8a5497cb0ad9",
  "status": "FETCH_MENU_INVALID_PAYLOAD",
  "last_updated_at": "2020-03-24T10:03:49.614Z",
  "details": [
    "Invalid section [\"Menus\"]: Section must contain at least one product"
  ]
}

Possible Status Values:

StatusDescription
SUCCESSThe menu update process has been successfully completed
PROCESSINGThe menu update process is still ongoing
FETCH_MENU_INVALID_PAYLOADFailed due to an invalid JSON input
FETCH_MENU_SERVER_ERRORServer error when fetching menu
FETCH_MENU_UNAUTHORIZEDUnauthorized
NOT_PROCESSEDFailed due to incorrect integration configuration
LIMIT_EXCEEDEDMaximum number of daily menu updates exceeded
GLOVO_ERRORFailed due to an error in the Glovo system

INFO

In case the status indicates an error, the endpoint returns additional information in the details field to help understand the cause of the error.


Modify Product V3 ​

POST /api/v3/item/modify/stores/{storeId}/products/{productId} ​

Update an individual product in a Glovo store. Allows modification of price and/or availability.

Parameters:

ParameterInTypeRequired
storeIdpathstringYes
productIdpathstringYes

Request Body ModifyProduct:

json
{
  "price": 10.0,
  "available": true
}
FieldTypeDescription
pricenumber (double)The new price of the product. If not present or null, will not be updated
availablebooleanWhether the product is available. If not present or null, will not be updated
bash
curl -X POST \
  'https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/item/modify/stores/partner__001/products/burger1' \
  -H 'Authorization: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"price": 10.0, "available": true}'
python
import requests

url = "https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/item/modify/stores/partner__001/products/burger1"
response = requests.post(url, json={"price": 10.0, "available": True}, headers={"Authorization": "YOUR_API_KEY"})

Response Schema ModifyProductResult:

json
{
  "id": "burger1",
  "name": "Burger Large",
  "price": "10.0",
  "image_url": "https://server.com/image",
  "description": "A large cheeseburger",
  "available": true,
  "error": null
}

Responses: 200 Product updated | 400 Invalid payload | 401 Unauthorized | 500 Server error


Modify Attribute V3 ​

POST /api/v3/item/modify/stores/{storeId}/attributes/{attributeId} ​

Update an individual attribute in a Glovo store.

Parameters:

ParameterInTypeRequired
storeIdpathstringYes
attributeIdpathstringYes

Request Body ModifyAttribute:

json
{
  "price_impact": 1.5,
  "available": true
}
FieldTypeDescription
price_impactnumber (double)The new price of the attribute. If not present or null, will not be updated
availablebooleanWhether the attribute is available. If not present or null, will not be updated
bash
curl -X POST \
  'https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/item/modify/stores/partner__001/attributes/side1' \
  -H 'Authorization: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"price_impact": 1.5, "available": true}'

Response Schema ModifyAttributeResult:

json
{
  "id": "side1",
  "name": "French fries",
  "selected_by_default": true,
  "price": "1.5",
  "available": true,
  "error": null
}

Responses: 200 Attribute updated | 400 Invalid payload | 401 Unauthorized | 500 Server error


Bulk Update V3 ​

POST /api/v3/item/modify/stores/{storeId}/bulk ​

Bulk update for products and attributes. Asynchronous operation — returns transaction_id.

Parameters:

ParameterInTypeRequired
storeIdpathstringYes

Request Body BulkUpdateItems:

json
{
  "products": [
    {
      "id": "burger1",
      "name": "Burger Large",
      "price": 10.0,
      "image_url": "https://server.com/image",
      "extra_image_urls": [
        "https://i.imgur.com/Tsj3NOK.png",
        "https://i.imgur.com/Qj5DlEH.png"
      ],
      "restrictions": {
        "is_alcoholic": false
      },
      "available": true
    }
  ],
  "attributes": [
    {
      "id": "side1",
      "name": "French fries",
      "price_impact": 1.5,
      "available": true
    }
  ]
}

Schema BulkUpdateItemsProducts ​

FieldTypeDescription
idstringUnique identifier of the product within the store
namestringProduct name
pricenumberProduct price
image_urlstringMain product image URL (HTTPS)
extra_image_urlsarray[string]Additional image URLs (HTTPS, max 9 — if more are sent, only the first 9 will be processed). Displayed on the product detail page in the same order as in the array, always after the main image
restrictionsMenuRestrictionsProduct restrictions
availablebooleanWhether the product is available

Schema MenuRestrictions ​

FieldTypeDescription
is_alcoholicbooleanIndicates whether the product is an alcoholic beverage. It will trigger a user flow according to restrictions for stores in Poland and Romania. To activate alcohol restriction, contact the integration team at pos.integrations@appsmart.ro

Schema BulkUpdateItemsAttributes ​

FieldTypeDescription
idstringUnique identifier of the attribute within the store
namestringAttribute name
price_impactnumberAttribute price
availablebooleanWhether the attribute is available
bash
curl -X POST \
  'https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/item/modify/stores/partner__001/bulk' \
  -H 'Authorization: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d @bulk-update.json

Response Schema BulkUpdateItemsStatus:

json
{
  "error": null,
  "message": null,
  "transaction_id": "a946a2c7-f4e7-46ac-ae63-8a5497cb0ad9",
  "status": "PARTIALLY_PROCESSED",
  "last_updated_at": "2020-03-24T10:03:49.614Z",
  "details": [
    "Products updated: [11111, 22222]",
    "Products not updated: [12345, 56789]",
    "Attributes updated: [33333, 44444]",
    "Attributes not updated: [67890, 45678]"
  ]
}

Bulk Update Statuses:

StatusDescription
SUCCESSAll items updated successfully
PROCESSINGProcessing in progress
PARTIALLY_PROCESSEDOnly some items were updated
NOT_PROCESSEDNo items were processed
GLOVO_ERRORGlovo system error

Bulk Update Check Status V3 ​

GET /api/v3/item/modify/checkstatus/bulk/{trackingCode} ​

Check status for bulk update operation.

Parameters:

ParameterInTypeRequired
trackingCodepathstringYes
bash
curl -X GET \
  'https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/item/modify/checkstatus/bulk/a946a2c7-f4e7-46ac-ae63-8a5497cb0ad9' \
  -H 'Authorization: YOUR_API_KEY'

Response: BulkUpdateItemsStatus schema (see above)


Update Order Status V3 ​

POST /api/v3/order/stores/orders/status ​

Allows the update of the order status during different stages of preparation.

Request Body OrderStatusChangeRequestVO:

json
{
  "store_id": "partner__001",
  "partner_name": "partner",
  "order_id": "616342127",
  "status": "ACCEPTED"
}
FieldTypeDescription
store_idstringStore ID
partner_namestringPartner name
order_idstringOrder ID
statusstringNew status (see below)

Available Statuses:

StatusDescription
ACCEPTEDThe order has been accepted by the store. If you don't accept the order, Glovo will still move forward — acceptance is not required to proceed
READY_FOR_PICKUPThe order is ready to be picked up by a courier or the customer (only available for orders delivered by Glovo couriers)
OUT_FOR_DELIVERYThe courier has collected the order and is now delivering to the customer (only available for Marketplace orders)
PICKED_UP_BY_CUSTOMERThe order has been picked up by the customer (only available for pick-up orders)
bash
curl -X POST \
  'https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/order/stores/orders/status' \
  -H 'Authorization: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"store_id":"partner__001","partner_name":"partner","order_id":"616342127","status":"ACCEPTED"}'

Responses: 200 Status updated | 400 Invalid payload | 401 Unauthorized | 500 Server error


Order Lifecycle V3 ​

PUT /api/v3/order-lifecycle/integrations/orders/{orderId}/accept/{storeId} ​

Accept order with optional preparation time.

Parameters:

ParameterInTypeDescription
orderIdpathstringUnique identifier of the order
storeIdpathstringUnique identifier of the store

Request Body:

json
{
  "committedPreparationTime": "2024-02-02T19:20:30Z"
}
FieldTypeDescription
committedPreparationTimestring (UTC Timestamp)Optional. The point in time at which the order is expected to be ready in the store. Used to estimate the courier's arrival at the store more accurately. ISO 8601 format, in UTC: YYYY-MM-DDThh:mm:ssZ.

Accepted range ​

The value is compared against the preparation time Glovo estimated for that order. Two separate conditions apply — this is not a symmetric tolerance:

estimated  <  committed  ≤  estimated + 900 seconds
  • Upper bound — the difference from the estimate may not exceed 900 seconds.
  • Lower bound — the value must be strictly greater than the estimate. There is no tolerance here: a value equal to the estimate, or below it even by one second, is rejected.

Adjustment logic that aligns the value to Glovo's estimate produces a rejection. The correct target is strictly above the estimate.

Response codes ​

CodeMeaning
204The order was accepted and the preparation time was registered. No content.
202The order was accepted, but the preparation time was not registered: either it was not sent, or it falls outside the accepted range. The response body carries the reason.
400The request body is not a JSON object (for example []). The order is not accepted by this request.

A rejected value does not affect the order — it stays accepted on both 204 and 202. Handling the two codes separately is recommended, so that the POS shows when a submitted time was not taken up.

The request body is always a JSON object. When no preparation time is submitted, send the empty object {}.

Example 202 response — time outside the range:

json
{
  "invalid-params": [
    {
      "name": "committedPreparationTime",
      "reason": "The difference in seconds between committed preparation time and estimated preparation time is exceeding [900] threshold. committed: [1953], estimated: [900]"
    }
  ],
  "title": "Your request parameters are not valid."
}

The reason message carries the applied threshold and both compared values. Reading the threshold from the message and logging it is recommended, rather than keeping a fixed value in code.

Example 202 response — time not sent:

A request without committedPreparationTime (body {}) also receives 202, with the reason below. The order is accepted; the response only states that no preparation time was registered. It is not an error and does not call for a new request.

json
{
  "invalid-params": [
    {
      "name": "committedPreparationTime",
      "reason": "Committed preparation time is missing."
    }
  ],
  "title": "Your request parameters are not valid."
}

The value is final ​

The preparation time is submitted once, on acceptance. There is no follow-up update operation: the remaining order lifecycle operations take only the identifiers, with no request body, so they cannot carry a revised time.

If preparation takes longer than announced, the only remaining signal is ready_for_pickup, sent when the order is actually ready. Accepting the same order a second time is rejected.

PUT /api/v3/order-lifecycle/integrations/orders/{orderId}/ready_for_pickup/{storeId} ​

Mark order as ready for pickup.

PUT /api/v3/order-lifecycle/integrations/orders/{orderId}/out_for_delivery/{storeId} ​

Mark order as out for delivery (Marketplace only).

PUT /api/v3/order-lifecycle/integrations/orders/{orderId}/customer_picked_up/{storeId} ​

Mark order as picked up by customer.


Scheduling V3 — Temporary Closing ​

PUT /api/v3/scheduling/stores/{storeId}/closing ​

Set a temporary closing for the store until a specified future date and time. This will override the normal operating hours.

Request Body TemporaryClosingRequest:

json
{
  "until": "2024-12-20T10:00:00+01:00"
}
FieldTypeRequiredDescription
untilstringYesThe date and time (with UTC offset) until which the store will be closed. ISO-8601 format

Responses:

StatusDescription
204Temporary closing set successfully
400Bad Request (invalid payload, date in the past, invalid storeId)
401Unauthorized (invalid API token)
403Forbidden (API token does not have permissions)
404Not Found (store not found)
500Internal Server Error

GET /api/v3/scheduling/stores/{storeId}/closing ​

Get the status of the store's active temporary closing, if one exists.

Response Schema TemporaryClosingStatusResponse:

json
{
  "until": "2024-12-20T10:00:00+01:00"
}
FieldTypeDescription
untilstring (nullable)The date and time until which the store is closed. null if there is no active closing

DELETE /api/v3/scheduling/stores/{storeId}/closing ​

Remove the store's active temporary closing. After removal, the store will follow its regular operating schedule.

INFO

Glovo may return 204 even if there is no active closing to remove.

bash
curl -X PUT \
  'https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/scheduling/stores/partner__001/closing' \
  -H 'Authorization: YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{"until": "2024-12-20T10:00:00+01:00"}'
bash
curl -X GET \
  'https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/scheduling/stores/partner__001/closing' \
  -H 'Authorization: YOUR_API_KEY'
bash
curl -X DELETE \
  'https://prod.store-management.glovo.alb.app.onlineservice.io/api/v3/scheduling/stores/partner__001/closing' \
  -H 'Authorization: YOUR_API_KEY'