Endpoint
GET /api/v1/feeds/{platform}
| Parameter | Values |
|---|---|
platform | google, meta, openai |
Basic Request
curl "https://app.alana.shopping/api/v1/feeds/google" \
-H "X-API-Key: sk_live_your_api_key"
const res = await fetch(
"https://app.alana.shopping/api/v1/feeds/google",
{ headers: { "X-API-Key": "sk_live_your_api_key" } }
);
const xml = await res.text(); // Google returns XML
import requests
res = requests.get(
"https://app.alana.shopping/api/v1/feeds/google",
headers={"X-API-Key": "sk_live_your_api_key"},
)
print(res.text) # XML content
Format Options
| Platform | Default Format | Accept Header Override |
|---|---|---|
google | application/xml | application/x-ndjson |
meta | text/csv | application/x-ndjson |
openai | application/json | application/x-ndjson |
NDJSON Streaming
For large catalogs, request NDJSON to process products one at a time:curl "https://app.alana.shopping/api/v1/feeds/google" \
-H "X-API-Key: sk_live_your_api_key" \
-H "Accept: application/x-ndjson"
const res = await fetch(
"https://app.alana.shopping/api/v1/feeds/google",
{
headers: {
"X-API-Key": "sk_live_your_api_key",
Accept: "application/x-ndjson",
},
}
);
const reader = res.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const lines = decoder.decode(value).split("\n").filter(Boolean);
for (const line of lines) {
const product = JSON.parse(line);
console.log(product.id, product.title);
}
}
import requests, json
with requests.get(
"https://app.alana.shopping/api/v1/feeds/google",
headers={
"X-API-Key": "sk_live_your_api_key",
"Accept": "application/x-ndjson",
},
stream=True,
) as res:
for line in res.iter_lines():
if line:
product = json.loads(line)
print(product["id"], product["title"])
ETag and Delta Feeds
UseETag for efficient polling — only download a new feed when content has changed:
# First request — save the ETag
curl -I "https://app.alana.shopping/api/v1/feeds/google" \
-H "X-API-Key: sk_live_your_api_key"
# ETag: "abc123def456"
# Subsequent requests — skip download if unchanged
curl "https://app.alana.shopping/api/v1/feeds/google" \
-H "X-API-Key: sk_live_your_api_key" \
-H "If-None-Match: \"abc123def456\""
# Returns 304 Not Modified if feed hasn't changed
let etag = null;
async function pollFeed() {
const headers = { "X-API-Key": "sk_live_your_api_key" };
if (etag) headers["If-None-Match"] = etag;
const res = await fetch(
"https://app.alana.shopping/api/v1/feeds/google",
{ headers }
);
if (res.status === 304) {
console.log("Feed unchanged");
return null;
}
etag = res.headers.get("ETag");
return await res.text();
}
import requests
etag = None
def poll_feed():
global etag
headers = {"X-API-Key": "sk_live_your_api_key"}
if etag:
headers["If-None-Match"] = etag
res = requests.get(
"https://app.alana.shopping/api/v1/feeds/google",
headers=headers,
)
if res.status_code == 304:
print("Feed unchanged")
return None
etag = res.headers.get("ETag")
return res.text
Response Headers
| Header | Description |
|---|---|
ETag | Feed content hash for conditional requests |
Last-Modified | Timestamp of last feed generation |
X-Feed-Product-Count | Number of products in the feed |
Cache-Control | max-age=900 (15-minute cache) |
Query Parameters
| Parameter | Type | Description |
|---|---|---|
catalog_id | string | Filter to a specific catalog (optional) |
limit | integer | Max products per page (default: all) |
offset | integer | Pagination offset |