curl --request POST \
--url https://search.glood.ai/api/storefront/v1/headless/instant-search \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'x-shop: <x-shop>' \
--data '
{
"query": "sho",
"locale": "en-US",
"market": 123,
"limit": 50,
"objects": [],
"view": "product_details",
"trending": {
"type": "searches",
"period": "7d",
"category": "<string>",
"limit": 20
},
"visitor_id": "<string>",
"client_id": "<string>",
"customer_id": "<string>"
}
'import requests
url = "https://search.glood.ai/api/storefront/v1/headless/instant-search"
payload = {
"query": "sho",
"locale": "en-US",
"market": 123,
"limit": 50,
"objects": [],
"view": "product_details",
"trending": {
"type": "searches",
"period": "7d",
"category": "<string>",
"limit": 20
},
"visitor_id": "<string>",
"client_id": "<string>",
"customer_id": "<string>"
}
headers = {
"x-shop": "<x-shop>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-shop': '<x-shop>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
query: 'sho',
locale: 'en-US',
market: 123,
limit: 50,
objects: [],
view: 'product_details',
trending: {type: 'searches', period: '7d', category: '<string>', limit: 20},
visitor_id: '<string>',
client_id: '<string>',
customer_id: '<string>'
})
};
fetch('https://search.glood.ai/api/storefront/v1/headless/instant-search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://search.glood.ai/api/storefront/v1/headless/instant-search",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'query' => 'sho',
'locale' => 'en-US',
'market' => 123,
'limit' => 50,
'objects' => [
],
'view' => 'product_details',
'trending' => [
'type' => 'searches',
'period' => '7d',
'category' => '<string>',
'limit' => 20
],
'visitor_id' => '<string>',
'client_id' => '<string>',
'customer_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"x-shop: <x-shop>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://search.glood.ai/api/storefront/v1/headless/instant-search"
payload := strings.NewReader("{\n \"query\": \"sho\",\n \"locale\": \"en-US\",\n \"market\": 123,\n \"limit\": 50,\n \"objects\": [],\n \"view\": \"product_details\",\n \"trending\": {\n \"type\": \"searches\",\n \"period\": \"7d\",\n \"category\": \"<string>\",\n \"limit\": 20\n },\n \"visitor_id\": \"<string>\",\n \"client_id\": \"<string>\",\n \"customer_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-shop", "<x-shop>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://search.glood.ai/api/storefront/v1/headless/instant-search")
.header("x-shop", "<x-shop>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"query\": \"sho\",\n \"locale\": \"en-US\",\n \"market\": 123,\n \"limit\": 50,\n \"objects\": [],\n \"view\": \"product_details\",\n \"trending\": {\n \"type\": \"searches\",\n \"period\": \"7d\",\n \"category\": \"<string>\",\n \"limit\": 20\n },\n \"visitor_id\": \"<string>\",\n \"client_id\": \"<string>\",\n \"customer_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://search.glood.ai/api/storefront/v1/headless/instant-search")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-shop"] = '<x-shop>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"query\": \"sho\",\n \"locale\": \"en-US\",\n \"market\": 123,\n \"limit\": 50,\n \"objects\": [],\n \"view\": \"product_details\",\n \"trending\": {\n \"type\": \"searches\",\n \"period\": \"7d\",\n \"category\": \"<string>\",\n \"limit\": 20\n },\n \"visitor_id\": \"<string>\",\n \"client_id\": \"<string>\",\n \"customer_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"query": "sho",
"corrected_query": "shoe",
"autocorrect": {
"original_query": "sho",
"corrected_query": "shoe",
"confidence": 0.92,
"corrections": [],
"alternatives": []
},
"suggestions": [
{ "text": "shoes", "type": "keyword", "object_count": 120, "search_count": 45 }
],
"products": {
"results": [
{
"product_id": 9311227838783,
"title": "Running Shoe",
"handle": "running-shoe",
"product_type": "Shoes",
"vendor": "Acme",
"tags": ["sale", "summer"],
"price": 49.99,
"compare_at_price": 69.99,
"display_price": 49.99,
"display_compare_at_price": 69.99,
"display_currency": "USD",
"original_currency": "USD",
"currency_rate": 1,
"available_for_sale": true,
"is_in_stock": true,
"total_inventory": 42,
"image": { "id": "gid://shopify/ProductImage/1", "url": "https://cdn.shopify.com/s/files/1/shoe.jpg", "width": 800, "height": 800, "alt_text": "Running Shoe" },
"featured_media": null,
"media": [],
"options": [ { "id": 111, "name": "Size", "position": 1, "values": ["S", "M", "L"] } ],
"variants": [
{
"variant_id": 456,
"title": "M",
"display_name": "Running Shoe - M",
"sku": "RS-M",
"position": 1,
"price": 49.99,
"compare_at_price": 69.99,
"available_for_sale": true,
"is_in_stock": true,
"sellable_online_quantity": 10,
"selected_options": [ { "name": "Size", "value": "M" } ],
"image": null
}
],
"metafields": [ { "namespace": "custom", "key": "material", "value": "leather" } ]
}
],
"total": 120
},
"collections": { "results": [ { "collection_id": 1, "title": "Shoes", "handle": "shoes", "image": null } ], "total": 3 },
"pages": { "results": [ { "page_id": 1, "title": "Size Guide", "handle": "size-guide" } ], "total": 1 },
"articles": { "results": [], "total": 0 },
"trending": { "searches": [], "products": [] },
"metadata": { "query_time": 12, "locale": "en-US", "market": null, "min_query_length": 2 }
}
{
"query": "",
"corrected_query": null,
"autocorrect": null,
"suggestions": [],
"products": { "results": [], "total": 0 },
"collections": { "results": [], "total": 0 },
"pages": { "results": [], "total": 0 },
"articles": { "results": [], "total": 0 },
"trending": {
"searches": [ { "term": "sale", "translated_term": "sale", "search_count": 300 } ],
"products": []
},
"metadata": { "query_time": 8, "locale": "en-US", "market": null, "min_query_length": 2 }
}
{
"error": [
{
"message": "\"limit\" must be less than or equal to 100",
"path": ["limit"],
"type": "number.max",
"context": { "limit": 100, "value": 500, "label": "limit", "key": "limit" }
}
],
"ok": false
}
Instant Search
Type-ahead search in a single call: products / collections / pages / articles + keyword suggestions + autocorrect, plus an empty-state trending block. Auth: Authorization: Bearer <gl_sf_...> + x-shop.
curl --request POST \
--url https://search.glood.ai/api/storefront/v1/headless/instant-search \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--header 'x-shop: <x-shop>' \
--data '
{
"query": "sho",
"locale": "en-US",
"market": 123,
"limit": 50,
"objects": [],
"view": "product_details",
"trending": {
"type": "searches",
"period": "7d",
"category": "<string>",
"limit": 20
},
"visitor_id": "<string>",
"client_id": "<string>",
"customer_id": "<string>"
}
'import requests
url = "https://search.glood.ai/api/storefront/v1/headless/instant-search"
payload = {
"query": "sho",
"locale": "en-US",
"market": 123,
"limit": 50,
"objects": [],
"view": "product_details",
"trending": {
"type": "searches",
"period": "7d",
"category": "<string>",
"limit": 20
},
"visitor_id": "<string>",
"client_id": "<string>",
"customer_id": "<string>"
}
headers = {
"x-shop": "<x-shop>",
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {
'x-shop': '<x-shop>',
Authorization: 'Bearer <token>',
'Content-Type': 'application/json'
},
body: JSON.stringify({
query: 'sho',
locale: 'en-US',
market: 123,
limit: 50,
objects: [],
view: 'product_details',
trending: {type: 'searches', period: '7d', category: '<string>', limit: 20},
visitor_id: '<string>',
client_id: '<string>',
customer_id: '<string>'
})
};
fetch('https://search.glood.ai/api/storefront/v1/headless/instant-search', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://search.glood.ai/api/storefront/v1/headless/instant-search",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'query' => 'sho',
'locale' => 'en-US',
'market' => 123,
'limit' => 50,
'objects' => [
],
'view' => 'product_details',
'trending' => [
'type' => 'searches',
'period' => '7d',
'category' => '<string>',
'limit' => 20
],
'visitor_id' => '<string>',
'client_id' => '<string>',
'customer_id' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json",
"x-shop: <x-shop>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://search.glood.ai/api/storefront/v1/headless/instant-search"
payload := strings.NewReader("{\n \"query\": \"sho\",\n \"locale\": \"en-US\",\n \"market\": 123,\n \"limit\": 50,\n \"objects\": [],\n \"view\": \"product_details\",\n \"trending\": {\n \"type\": \"searches\",\n \"period\": \"7d\",\n \"category\": \"<string>\",\n \"limit\": 20\n },\n \"visitor_id\": \"<string>\",\n \"client_id\": \"<string>\",\n \"customer_id\": \"<string>\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-shop", "<x-shop>")
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://search.glood.ai/api/storefront/v1/headless/instant-search")
.header("x-shop", "<x-shop>")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"query\": \"sho\",\n \"locale\": \"en-US\",\n \"market\": 123,\n \"limit\": 50,\n \"objects\": [],\n \"view\": \"product_details\",\n \"trending\": {\n \"type\": \"searches\",\n \"period\": \"7d\",\n \"category\": \"<string>\",\n \"limit\": 20\n },\n \"visitor_id\": \"<string>\",\n \"client_id\": \"<string>\",\n \"customer_id\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://search.glood.ai/api/storefront/v1/headless/instant-search")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-shop"] = '<x-shop>'
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"query\": \"sho\",\n \"locale\": \"en-US\",\n \"market\": 123,\n \"limit\": 50,\n \"objects\": [],\n \"view\": \"product_details\",\n \"trending\": {\n \"type\": \"searches\",\n \"period\": \"7d\",\n \"category\": \"<string>\",\n \"limit\": 20\n },\n \"visitor_id\": \"<string>\",\n \"client_id\": \"<string>\",\n \"customer_id\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"query": "sho",
"corrected_query": "shoe",
"autocorrect": {
"original_query": "sho",
"corrected_query": "shoe",
"confidence": 0.92,
"corrections": [],
"alternatives": []
},
"suggestions": [
{ "text": "shoes", "type": "keyword", "object_count": 120, "search_count": 45 }
],
"products": {
"results": [
{
"product_id": 9311227838783,
"title": "Running Shoe",
"handle": "running-shoe",
"product_type": "Shoes",
"vendor": "Acme",
"tags": ["sale", "summer"],
"price": 49.99,
"compare_at_price": 69.99,
"display_price": 49.99,
"display_compare_at_price": 69.99,
"display_currency": "USD",
"original_currency": "USD",
"currency_rate": 1,
"available_for_sale": true,
"is_in_stock": true,
"total_inventory": 42,
"image": { "id": "gid://shopify/ProductImage/1", "url": "https://cdn.shopify.com/s/files/1/shoe.jpg", "width": 800, "height": 800, "alt_text": "Running Shoe" },
"featured_media": null,
"media": [],
"options": [ { "id": 111, "name": "Size", "position": 1, "values": ["S", "M", "L"] } ],
"variants": [
{
"variant_id": 456,
"title": "M",
"display_name": "Running Shoe - M",
"sku": "RS-M",
"position": 1,
"price": 49.99,
"compare_at_price": 69.99,
"available_for_sale": true,
"is_in_stock": true,
"sellable_online_quantity": 10,
"selected_options": [ { "name": "Size", "value": "M" } ],
"image": null
}
],
"metafields": [ { "namespace": "custom", "key": "material", "value": "leather" } ]
}
],
"total": 120
},
"collections": { "results": [ { "collection_id": 1, "title": "Shoes", "handle": "shoes", "image": null } ], "total": 3 },
"pages": { "results": [ { "page_id": 1, "title": "Size Guide", "handle": "size-guide" } ], "total": 1 },
"articles": { "results": [], "total": 0 },
"trending": { "searches": [], "products": [] },
"metadata": { "query_time": 12, "locale": "en-US", "market": null, "min_query_length": 2 }
}
{
"query": "",
"corrected_query": null,
"autocorrect": null,
"suggestions": [],
"products": { "results": [], "total": 0 },
"collections": { "results": [], "total": 0 },
"pages": { "results": [], "total": 0 },
"articles": { "results": [], "total": 0 },
"trending": {
"searches": [ { "term": "sale", "translated_term": "sale", "search_count": 300 } ],
"products": []
},
"metadata": { "query_time": 8, "locale": "en-US", "market": null, "min_query_length": 2 }
}
{
"error": [
{
"message": "\"limit\" must be less than or equal to 100",
"path": ["limit"],
"type": "number.max",
"context": { "limit": 100, "value": 500, "label": "limit", "key": "limit" }
}
],
"ok": false
}
{
"query": "sho",
"corrected_query": "shoe",
"autocorrect": {
"original_query": "sho",
"corrected_query": "shoe",
"confidence": 0.92,
"corrections": [],
"alternatives": []
},
"suggestions": [
{ "text": "shoes", "type": "keyword", "object_count": 120, "search_count": 45 }
],
"products": {
"results": [
{
"product_id": 9311227838783,
"title": "Running Shoe",
"handle": "running-shoe",
"product_type": "Shoes",
"vendor": "Acme",
"tags": ["sale", "summer"],
"price": 49.99,
"compare_at_price": 69.99,
"display_price": 49.99,
"display_compare_at_price": 69.99,
"display_currency": "USD",
"original_currency": "USD",
"currency_rate": 1,
"available_for_sale": true,
"is_in_stock": true,
"total_inventory": 42,
"image": { "id": "gid://shopify/ProductImage/1", "url": "https://cdn.shopify.com/s/files/1/shoe.jpg", "width": 800, "height": 800, "alt_text": "Running Shoe" },
"featured_media": null,
"media": [],
"options": [ { "id": 111, "name": "Size", "position": 1, "values": ["S", "M", "L"] } ],
"variants": [
{
"variant_id": 456,
"title": "M",
"display_name": "Running Shoe - M",
"sku": "RS-M",
"position": 1,
"price": 49.99,
"compare_at_price": 69.99,
"available_for_sale": true,
"is_in_stock": true,
"sellable_online_quantity": 10,
"selected_options": [ { "name": "Size", "value": "M" } ],
"image": null
}
],
"metafields": [ { "namespace": "custom", "key": "material", "value": "leather" } ]
}
],
"total": 120
},
"collections": { "results": [ { "collection_id": 1, "title": "Shoes", "handle": "shoes", "image": null } ], "total": 3 },
"pages": { "results": [ { "page_id": 1, "title": "Size Guide", "handle": "size-guide" } ], "total": 1 },
"articles": { "results": [], "total": 0 },
"trending": { "searches": [], "products": [] },
"metadata": { "query_time": 12, "locale": "en-US", "market": null, "min_query_length": 2 }
}
{
"query": "",
"corrected_query": null,
"autocorrect": null,
"suggestions": [],
"products": { "results": [], "total": 0 },
"collections": { "results": [], "total": 0 },
"pages": { "results": [], "total": 0 },
"articles": { "results": [], "total": 0 },
"trending": {
"searches": [ { "term": "sale", "translated_term": "sale", "search_count": 300 } ],
"products": []
},
"metadata": { "query_time": 8, "locale": "en-US", "market": null, "min_query_length": 2 }
}
{
"error": [
{
"message": "\"limit\" must be less than or equal to 100",
"path": ["limit"],
"type": "number.max",
"context": { "limit": 100, "value": 500, "label": "limit", "key": "limit" }
}
],
"ok": false
}
Authorizations
Bearer authentication header of the form Bearer <token>, where <token> is your auth token.
Headers
Shopify store URL. Resolves the shop for the request (headless does not accept ?shop=).
"shop.myshopify.com"
Body
Request body
Instant search request. Union of the legacy instant-results, instant-suggest and trending inputs.
Search term. Required but may be an empty string (empty / too-short queries return the trending block).
"sho"
BCP-47 locale.
Shopify market id.
Per-type result limit.
1 <= x <= 100Which result blocks to return. Defaults to config.instant_search_objects. query_suggestion/auto_suggestion -> keyword suggestions; autocorrect -> spell-correct.
product, collection, page, article, blog, query_suggestion, auto_suggestion, autocorrect Product render mode.
product_details, product_ids Options for the empty-state trending block.
Show child attributes
Show child attributes
Anonymous device/browser UID (the gl_s_uid cookie). The primary personalization key; stays stable when a customer logs in.
Per-session / per-device identifier.
Shopify customer id. Present only when the shopper is logged in; enables customer-level personalization.
Response
Instant search results
Instant search results: products / collections / pages / articles + suggestions + autocorrect + trending.
Echo of the requested query.
Convenience mirror of autocorrect.corrected_query; null when no correction.
Spell-correction result, or null when not requested / disabled.
Show child attributes
Show child attributes
Keyword suggestions.
Show child attributes
Show child attributes
Product results block.
Show child attributes
Show child attributes
Collection results block.
Show child attributes
Show child attributes
Page results block.
Show child attributes
Show child attributes
Article results block.
Show child attributes
Show child attributes
Populated only when the query is empty / below the minimum length; otherwise empty arrays.
Show child attributes
Show child attributes
Response metadata.
Show child attributes
Show child attributes
Was this page helpful?