For AI Agents
How to consume feeds programmatically
Overview
GXO Feeds provides machine-readable product catalogs in two formats: JSON and NDJSON. All feeds are validated against the ACP specification and updated regularly.
Feed Discovery
Start by fetching the global feed index:
GET https://feeds.gxo.dev/v1/index.jsonResponse: Array of feed metadata with URLs
Consuming Feeds
Once you've identified a feed, fetch it using the provided URL. Feeds are available in three formats:
- JSON: Complete feed in a single JSON object
- NDJSON: Newline-delimited JSON, one product per line (useful for streaming)
- Manifest: Metadata about the feed (hash, item count, generation time)
Example: Fetching a Feed
Fetch feed manifest:
GET https://feeds.gxo.dev/v1/accounts/{accountId}/feeds/{feedId}.manifest.jsonFetch full feed:
GET https://feeds.gxo.dev/v1/accounts/{accountId}/feeds/{feedId}.jsonStream feed (NDJSON):
GET https://feeds.gxo.dev/v1/accounts/{accountId}/feeds/{feedId}.ndjsonResponse Headers
All v1 endpoints include standard headers:
X-ACP-Version: Protocol version (currently 1.0)Cache-Control: Cache directives for optimal performanceAccess-Control-Allow-Origin: CORS enabledETag: Content hash for conditional requests
Rate Limits
Check the rate limit policy at /v1/ratelimit.json. Current limits:
- 60 requests per minute
- 1,000 requests per hour
- 10,000 requests per day
Code Examples
Fetch a single brand feedcurl
curl -H "User-Agent: MyAgent/1.0" \
https://feeds.gxo.dev/v1/brands/acme-electronics/feed.jsonPoll a brand feed with hash comparison (Node.js)node
import fetch from 'node-fetch';
async function pollBrandFeed(brandSlug) {
// 1. Fetch the manifest to check for updates
const manifestUrl = `https://feeds.gxo.dev/v1/brands/${brandSlug}/manifest.json`;
const manifestRes = await fetch(manifestUrl);
const manifest = await manifestRes.json();
// 2. Check if feed hash has changed
const currentHash = manifest.feedHash;
const cachedHash = getCachedHash(brandSlug); // your cache
if (currentHash === cachedHash) {
console.log('Feed unchanged, using cache');
return getCachedFeed(brandSlug);
}
// 3. Fetch the updated feed
const feedUrl = manifest.feedUrl;
const feedRes = await fetch(feedUrl, {
headers: {
'If-None-Match': cachedHash,
'User-Agent': 'MyAgent/1.0'
}
});
if (feedRes.status === 304) {
return getCachedFeed(brandSlug);
}
const feed = await feedRes.json();
cacheFeed(brandSlug, feed, currentHash);
return feed;
}Iterate through all brands (Python)python
import requests
def poll_all_brands():
"""Poll the index to discover all brands"""
index_url = "https://feeds.gxo.dev/v1/index.json"
response = requests.get(index_url, headers={
"User-Agent": "MyAgent/1.0"
})
index = response.json()
for brand in index["brands"]:
brand_slug = brand["slug"]
manifest_url = brand["manifestUrl"]
# Fetch manifest
manifest_res = requests.get(manifest_url)
manifest = manifest_res.json()
# Check ACP version
acp_version = manifest.get("acpVersion", "1.0")
print(f"Brand: {brand_slug}, ACP: {acp_version}")
# Fetch feed if needed
feed_url = manifest["feedUrl"]
feed_res = requests.get(feed_url)
feed = feed_res.json()
# Process products
for product in feed["products"]:
print(f" - {product['name']}: {product['price']}")