OpenAI Product Feed API for Magento 2 — module reference
OpenAI Product Feed API is a Magento 2 REST implementation of the OpenAI Agentic Commerce Protocol (ACP) feed API. It serves Feeds, Products and Promotions, so ChatGPT can read and update your catalog over an API, next to the daily file upload.
OpenAI’s advice is to send the full feed daily as a file, and send changes through the API. The file comes from OpenAI Product Feed. This module is the API part.
What it does
- Every endpoint needs a bearer token, as the ACP specification requires.
- Feeds are stored in the database, so they survive cache flushes and restarts.
- Product export is paginated and includes configurable product variants.
- Promotions come from Magento Cart Price Rules, with coupon codes and free shipping.
Requirements
| Magento | not declared (Open Source, Mage-OS or Adobe Commerce) — magento/framework * |
|---|---|
| PHP | 8.1+ — >=8.1 |
| Other angeo modules | angeo/module-openai-product-feed ^2.0 |
Installation
composer require angeo/module-openai-product-feed-api
bin/magento module:enable Angeo_OpenAiProductFeedApi
bin/magento setup:upgrade
bin/magento setup:di:compile # production mode only
bin/magento cache:flush
Authentication
Every endpoint needs a token with the Angeo_OpenAiProductFeedApi::manage_feeds permission.
- Go to System → Extensions → Integrations → Add New Integration.
- On the API tab, select Angeo — Manage Product Feed API (under Marketing).
- Save, Activate and copy the Access Token.
- Give that token to OpenAI as the feed API key. Use it in
Authorization: Bearerfor your own calls too.
Requests without a valid token get 401 Unauthorized.
Endpoints
| Method | Path | What it does |
|---|---|---|
POST | /rest/V1/angeo/product_feeds | Create a feed |
GET | /rest/V1/angeo/product_feeds | List all feeds (beyond the ACP spec) |
GET | /rest/V1/angeo/product_feeds/:id | Feed details |
GET | /rest/V1/angeo/product_feeds/:id/products | Products, paginated |
POST | /rest/V1/angeo/product_feeds/:id/products/upsert | Upsert products (PATCH bridge) |
POST | /rest/V1/angeo/product_feeds/:id/products/invalidate | Reset the product cache of the feed |
GET | /rest/V1/angeo/product_feeds/:id/promotions | Promotions |
POST | /rest/V1/angeo/product_feeds/:id/promotions/upsert | Upsert promotions (PATCH bridge) |
An invalid target_country gives 400 Bad Request. Unknown feed or store ids give 404 Not Found, as in the ACP error model.
The PATCH rewrite (web server)
The ACP spec uses PATCH for upserts. Magento’s REST framework does not support PATCH. Add a rewrite before the request reaches Magento.
nginx, inside your server {} block:
location ~ ^/rest/V1/angeo/product_feeds/[^/]+/products$ {
if ($request_method = PATCH) { rewrite ^(.*)$ $1/upsert last; }
}
location ~ ^/rest/V1/angeo/product_feeds/[^/]+/promotions$ {
if ($request_method = PATCH) { rewrite ^(.*)$ $1/upsert last; }
}
Apache, in .htaccess in the Magento root:
RewriteCond %{REQUEST_METHOD} ^PATCH$
RewriteRule ^rest/V1/angeo/product_feeds/([^/]+)/products$ rest/V1/angeo/product_feeds/$1/products/upsert [L]
RewriteCond %{REQUEST_METHOD} ^PATCH$
RewriteRule ^rest/V1/angeo/product_feeds/([^/]+)/promotions$ rest/V1/angeo/product_feeds/$1/promotions/upsert [L]
Quick start
TOKEN="<integration access token>"
# 1. Create a feed
curl -X POST https://yourstore.com/rest/V1/angeo/product_feeds \
-H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
-d '{"targetCountry":"US","storeId":1}'
# 2. Read products, page 1, 100 per page
curl -H "Authorization: Bearer $TOKEN" \
"https://yourstore.com/rest/V1/angeo/product_feeds/<feed id>/products?page=1&pageSize=100"
# 3. Read promotions
curl -H "Authorization: Bearer $TOKEN" \
https://yourstore.com/rest/V1/angeo/product_feeds/<feed id>/promotions
# 4. Reset the product cache after catalog changes
curl -X POST -H "Authorization: Bearer $TOKEN" \
https://yourstore.com/rest/V1/angeo/product_feeds/<feed id>/products/invalidate
How caching works
- Catalog snapshot. Built from the catalog on the first
GETand kept until you invalidate it. Store-scoped feeds are built with frontend store emulation, so URLs, currency and locale match the store view. - Upsert overlay. Products sent through upsert are stored apart and merged over the snapshot when read. The overlay wins. A rebuild never drops upserted products.
- Page slices. Formatted answers are cached for 30 minutes. Any upsert clears them at once.
- **
/invalidate** resets everything for the feed: snapshot, overlay and pages.
Field mapping
| ACP product field | Magento source |
|---|---|
id | entity_id — stable |
title | Product name |
description.plain / .html | description / short_description |
url | Product URL with utm_medium and utm_source=chatgpt |
media | Gallery images |
variants[].price / list_price | Final price / original price, in minor units (cents) |
variants[].availability | in_stock / out_of_stock |
variants[].variant_options | Configurable attribute labels and values |
variants[].barcodes | ean, upc, gtin, barcode, isbn attributes |
variants[].seller | Name and policy links from the configuration |
| Cart price rule | ACP promotion field |
|---|---|
rule_id | id as promo_rule_{id} |
name | title |
| description + coupon code | description.plain |
| active flag + dates | status: active, scheduled, expired or disabled |
by_percent | percent_off |
by_fixed / cart_fixed | amount_off (minor units) |
| free shipping | free_shipping, can combine with a discount |
Configuration reference
All settings are under Stores → Configuration → Angeo → Product Feed API. The table shows each field, its config path (for bin/magento config:set) and its default value.
General (5)
| Setting | Config path | Default |
|---|---|---|
| Enabled | angeo_feed_api/general/enabled | Yes |
| Default Target Country | angeo_feed_api/general/target_country | US |
| UTM Medium | angeo_feed_api/general/utm_medium | feed |
| Include List Price | angeo_feed_api/general/include_list_price | Yes |
| Include Barcodes | angeo_feed_api/general/include_barcodes | Yes |
Seller Information (6)
| Setting | Config path | Default |
|---|---|---|
| Seller Name | angeo_feed_api/seller/name | — |
| Terms of Service URL | angeo_feed_api/seller/terms_of_service_url | — |
| Privacy Policy URL | angeo_feed_api/seller/privacy_policy_url | — |
| Refund Policy URL | angeo_feed_api/seller/refund_policy_url | — |
| Shipping Policy URL | angeo_feed_api/seller/shipping_policy_url | — |
| FAQ URL | angeo_feed_api/seller/faq_url | — |
Stored data and permissions
| Table | What it holds | Columns |
|---|---|---|
angeo_acp_feed | Angeo ACP Product Feeds | id, feed_id, target_country, store_id, updated_at, created_at |
FAQ
Do I need this module to appear in ChatGPT?
Not for the daily file. The file comes from OpenAI Product Feed. This API is for sending changes between daily files and for reading promotions.
Why do I need a web server rewrite?
The ACP spec uses PATCH for upserts, and Magento’s REST layer does not support PATCH. The rewrite turns PATCH into a POST to the /upsert path.
Where do promotions come from?
From active Magento cart price rules, including coupon codes, percentage and fixed discounts, and free shipping.
When should I call invalidate?
After big catalog changes, if you want the next read to rebuild the snapshot right away. Upserts clear the page cache on their own.
Is the API public?
No. Every endpoint needs an Integration token with the Manage Product Feed API permission. Requests without it get 401.
Related
- OpenAI Product Feed — the ChatGPT product feed CSV per store view, for all product types
- Rich Data — one linked JSON-LD graph per page, with offers and policies
- AEO Audit — score 20 AI-visibility signals from the command line
- All module reference pages · Compatibility matrix
This page was written from the README.md, composer.json and etc/*.xml files of tag 2.0.1, read on 16 October 2026. Settings, commands and defaults come straight from that code. If a newer release is out, the README on GitHub wins.