For website developers, agencies and e-commerce platforms

Keep stock, prices and availability current automatically.

If a business's stock, prices or availability change often, X-Protocols can read a file on their own website on a schedule and keep an assistant's answers current — no plugin from us to install, no ongoing integration work. This page is the entire contract.

On this page

The short version

Publish a small XML file at any URL on your own site. List one <item> per product or service whose availability changes. Register that URL once. We read it on the interval the business chose, and nothing else is required from you afterwards.

Open Connections Live data → Open → New live data stream

Setting up the source

Check what already exists before building anything. Roughly in order of how likely each is to be a 30-second answer rather than new work:

  • WooCommerce: check installed plugins for anything with "Feed", "Google Shopping" or "Merchant Center" in the name (e.g. "Product Feed PRO", "Google Listings & Ads"). Its settings page shows a feed URL directly.
  • Shopify: check Sales Channels for "Google & YouTube" — if installed, a feed already exists.
  • PrestaShop / Magento / other: search the admin for "product feed" or "Google Shopping export" — nearly every mainstream platform has an official or community module for this already.
  • Already found one for Google Shopping/Merchant Center? You're most of the way there — the format below is deliberately close to it. You likely only need to add or rename a handful of fields, not build one from scratch.
  • Nothing above applies? Building one from scratch is genuinely simple — see the format below. It is a static file your server (or even a scheduled script) can regenerate periodically; no framework, database driver or library is required on your end, just valid XML in this shape.

Once the file exists at a stable URL, register it: Open Connections, then Live data → Open → New live data stream. The business owner can do this themselves, or an agency can do it on their behalf. There is nothing else to configure — no key, no secret, no code.

The format

One <feed> element, one <item> per thing whose availability changes. Everything except id is optional:

xml feed.xml
<?xml version="1.0" encoding="UTF-8"?>
<feed>
  <item>
    <id>SKU-123</id>
    <availability>in_stock</availability>
    <price currency="EUR">49.90</price>
    <quantity>4</quantity>
    <location_id>store-1</location_id>
    <updated_at>2026-08-05T12:00:00Z</updated_at>
  </item>
  <item>
    <id>SKU-124</id>
    <availability>out_of_stock</availability>
  </item>
</feed>

Mapping, field by field

id is the join. It must match the reference code (external ID) of that same item in the business's records. An id that matches nothing is not an error and is not a warning you will see in your own logs — the update simply has nothing to attach to. If one thing on this page is worth checking twice, it is this.

FieldRequired?What it means
idRequiredYour own product/service code. Must match the reference code (external ID) used for that same item in the business's records.
availabilityOptionalin_stock or out_of_stock. Use this if you don't track an exact number.
quantityOptionalAn exact count, if you have one. Overrides availability when both are given.
priceOptionalA number, with a currency attribute (e.g. currency="EUR").
location_idOptionalOnly needed if the business has more than one location/warehouse and stock differs between them.
updated_atOptionalISO 8601 timestamp (e.g. 2026-08-05T12:00:00Z). If you leave it out, we use the time we read the file.

Refresh

The business picks the interval when the stream is created: every 5, 15 or 30 minutes, hourly, every 6 hours, or once a day. This is a scheduled read, not a real-time push. If a business needs stock to change within seconds, that is the push route — POST /ingest/{stream} in the API documentation — which does need a developer.

Each read sends the validators from the previous successful one, so an unchanged file costs your server a 304 and no transfer at all. Honouring ETag or Last-Modified on your side is worth doing and is not required.

http what we send
GET /your-feed.xml HTTP/1.1
User-Agent: X-Protocols-LiveDataFeed/1.0 (+https://x-protocols.com/docs/live-data-feed)
Accept: application/xml,text/xml
If-None-Match: "<etag from our last successful read>"
If-Modified-Since: <date from our last successful read>

That User-Agent is the one to allow-list if the site is behind a WAF or a bot filter. A feed that answers a browser and blocks us is the commonest reason a correctly formatted file never updates anything.

Access and authentication

The feed URLMust be reachable over plain http:// or https:// with no credentials at all. We send a User-Agent, an Accept and the conditional headers — no Authorization, no basic auth, no cookie. A feed behind any login is unreachable, and always will be.
Keeping it privatePut an unguessable random path in the URL (/feed/8f3c1a…xml) rather than a password. It is not indexed, it is not linked from anywhere, and it can be rotated by changing the path and re-registering.
Bearer tokensBelong to the query API — the keys a publisher creates in Developer access, which identify whoever is reading their published records. They are never presented to your server, and they have nothing to do with this feed.
Authenticated ingestionExists, and it is the other direction: POST /ingest/{stream}, signed HMAC-SHA256 with a shared secret. Use that when you want to push the moment something changes instead of publishing a file we read.

When something goes wrong

Every read records its outcome, and the business can see it on the stream's own page — including the failures, with the reason. What each failure does:

The URL cannot be reachedRecorded as a failed read. The previously loaded data stays as it was; nothing is deleted because a file went missing.
Any status other than 200 or 304Same: recorded with the status code, previous data kept.
The XML does not parseRecorded as invalid XML. Nothing in the file is applied — a half-parsed feed is worse than a stale one.
More than 50000 items, or over 16MBRefused whole. Split the feed or narrow it to the items whose availability actually changes.
An item with no idSkipped, not fatal. One bad row never blocks the rest of the file.
An id matching no recordAccepted and applied to nothing. This is the silent one; see the note on mapping above.

A stream that keeps failing is shown as failing on Connections rather than quietly retrying forever.