FluentCart REST API Research & Live Tests
Research date: 2026-10-08
Live site: opshell.dev, FluentCart and FluentCart Pro 1.7.0 (confirmed in the earlier read-only WP-CLI inspection)
Test scope: Route discovery, GET requests, and an approved least-privilege integration identity setup. No FluentCart product/order/customer/payment records or gateway settings were created or modified.
Executive result
The FluentCart REST API is the strongest supported automation interface for a future AI product workflow. The live WordPress REST index advertises both fluent-cart/v2 and legacy fluent-cart/v1 namespaces and 366 FluentCart route patterns (364 under v2, 2 under v1). The live API has extensive product CRUD, variations, pricing, downloadable files, bundles, tax/shipping configuration, reports, orders, customers, subscriptions, and settings routes.
Live checks confirmed the REST index and public shop API respond. The public product endpoint returned HTTP 200 and zero published products. An unauthenticated admin product listing returned HTTP 401 rest_forbidden. A dedicated non-admin integration identity and Application Password were then created through WP-CLI, and its authenticated product-list request returned HTTP 200. The identity was denied access to orders (403) and its attempt to publish a product was denied (403). A valid product draft was not created; no commerce records were written.
The site was initially behind Cloudflare Access. Following the user's direction to use the existing cfpa workflow and confirming its behavior in the AI-records history, cfpa --ipv6 opshell.dev was applied for this session. It updated the existing exact-domain Access bypass policy to this session's IPv4 and IPv6 /64; it did not change WordPress/FluentCart. The Access policy change is recorded as an access prerequisite, not a REST API mutation.
Live test record
Access and endpoints
| Test | Request | Result | Interpretation |
|---|---|---|---|
| Cloudflare Access | cfpa --ipv6 opshell.dev | Matched exactly one Access app; updated its existing bypass policy with current IPv4 and IPv6 /64 | HTTPS REST requests from this session can reach the WordPress origin. This edits Cloudflare Access only. |
| WordPress REST index | GET https://opshell.dev/wp-json/ | HTTP 200, JSON; namespaces include fluent-cart/v2 and fluent-cart/v1 | WordPress REST is exposed after Access authorization. |
| Live route discovery | Routes in REST index whose path starts /fluent-cart/ | 366 route patterns: v2 = 364, v1 = 2 | The installed API advertises a large surface; route-pattern count differs from documentation's operation count and method count. |
| Public product list | GET /wp-json/fluent-cart/v2/public/products?per_page=1 | HTTP 200, JSON; total = 0; returned = 0 | No published products were returned by the public catalog endpoint at test time. It does not establish private/admin catalog state. |
| Admin product list without credentials | GET /wp-json/fluent-cart/v2/products?per_page=1 | HTTP 401 JSON, code rest_forbidden, message “Sorry, you are not allowed to do that.” | Admin catalog calls require a logged-in WordPress identity with FluentCart products/view permission. |
| Authenticated product list | GET /wp-json/fluent-cart/v2/products?per_page=1 as the dedicated integration identity | HTTP 200, JSON; total = 0 | Application Password authentication and product-view permission work. |
| Out-of-scope route | GET /wp-json/fluent-cart/v2/orders?per_page=1 as the integration identity | HTTP 403, opshell_ai_fluentcart_route_restricted | The custom REST boundary denies non-product FluentCart routes. |
| Publish guard | POST /wp-json/fluent-cart/v2/products with post_status=publish and intentionally incomplete product body | HTTP 403, opshell_ai_product_draft_only | The guard blocks publishing before product validation. No product was created. |
| WP-CLI product post count (earlier test) | wp post list --post_type=fluent-products --post_status=publish/draft --format=count | Both returned 0; subsequent authenticated list also reported total 0 | No product was created during these tests. |
An initial request made before cfpa reached the Cloudflare Access login HTML with HTTP 200; that was an SSO page, not a successful REST response. The tests above were repeated after the Access policy update and were verified as JSON responses.
Test limitations
- The admin API's authentication and permission behavior is only tested for the unauthenticated denial. Valid application-password authentication,
products/view, and create permission are unverified on the live site. - The Application Password was generated by WP-CLI and stored in a protected local credential file outside the documentation/source repository. Its value is intentionally absent from all documentation and command output.
- No valid product create, update, or delete request was sent. The only POST test was an intentionally incomplete publish attempt that the draft-only guard denied before FluentCart validation. Pricing, variations, files, and checkout have not been live write-tested.
- Public product count zero should not be interpreted as proof that there are no draft/private products or that every API catalog query returns zero.
- The API root's route list is a route inventory, not a full OpenAPI specification: it may include multiple methods on one path, regex parameter patterns, legacy routes, and endpoints that differ by Pro/add-on state or permission.
API overview
The documented base URL is:
https://opshell.dev/wp-json/fluent-cart/v2
The live WordPress REST index advertises fluent-cart/v2 and fluent-cart/v1. The v2 namespace is the documented current API; use it for new work and treat v1 as compatibility surface only unless a particular installed operation requires otherwise.
Documented API surface
FluentCart's developer overview describes 367+ operations/endpoints across core and Pro areas. The live REST index exposed 366 FluentCart path patterns. These totals are not directly comparable: an operation can map to a route/method, and one route can expose more than one method. The following module inventory is drawn from the current docs; not all modules are guaranteed to be enabled in the target setup.
| Module | Main API capabilities | Strong AI use cases | Risk class |
|---|---|---|---|
| Products | Product CRUD/list/search, pricing, variations, options, media, inventory, downloads, bundles, upgrade paths, categories/tax/shipping classes, integrations, bulk actions | Draft product preparation, catalog QA, normalization, SKU/variant comparison, content and metadata suggestions | Writes require approval; draft-only product create is a good first write test |
| Orders | Search/list/detail, create/update/delete, status, payment transactions, refunds, address/customer changes, shipping, renewals, bulk operations, license generation | Support copilot, order lookup, fulfillment summaries, issue classification, reconciliation flags | Refunds, payment status, delete, address and fulfillment changes are sensitive |
| Customers | List/search/detail/create/update, addresses, notes/labels, user association, order history/statistics | Customer support context and draft responses, deduplication candidates, segmentation suggestions | Personal data; restrict output and retention; require approval to modify/export |
| Subscriptions | List/detail, lifecycle, pause/resume/cancel, renewal controls, payment-method changes, remote vendor IDs | Renewal dashboards, failed-payment triage, churn/retention analysis | Changes affect billing/access and require human authorization |
| Coupons | CRUD, eligibility, code usage, settings | Generate campaign drafts, validate discount calculations, analyze redemption | Activation/terms change commercial offer; approval needed |
| Tax | Tax settings/classes/rates/records, EU VAT and OSS options, product/category overrides | Completeness checks, explain configured values, create human review checklist | Legal/tax decisions and filing are human/accountant decisions |
| Shipping | Zones, methods/classes, packages, rates, zone ordering | Check missing weights/coverage, summarize shipping rules, prepare fulfillment | Carrier settings and delivery promises need owner approval |
| Settings and payment methods | Store, module, checkout and payment settings; connection info; PayPal webhook helpers; storage configuration | Readiness checklist, settings explanation, integration troubleshooting | Sensitive; never let AI change production payments, storage, credentials, or tax settings autonomously |
| Email notifications | Templates, settings, preview, enable/disable, reminders/digest | Draft/edit copy, audit shortcodes, preview for human review | A send/test endpoint can send messages; production enablement requires approval |
| Reports | Sales/revenue/orders/refunds/subscriptions/customers/products/retention/licenses/source/time analytics | Natural-language analysis, anomaly detection, summaries, trend hypotheses | Read-only usually; data exposure, metric definitions, and causal claims require care |
| Integrations | Add-ons and global/product feeds/settings | Integration mapping suggestions, workflow design, failed-feed diagnosis | Add-on install/activation and feed changes may execute external effects |
| Files/storage | File list, upload/delete, storage buckets and drivers | Metadata/asset checks, content processing in an isolated pipeline | Upload/delete, customer files and credentials are sensitive |
| Public shop/checkout | Public catalog/search/product views; checkout summaries, shipping methods, place order | Catalog Q&A and public product search; test-plan generation | Public reads are low risk; place-order creates order/payment side effects and must not be used as a casual test |
| Customer profile | Customer's own orders, downloads, addresses, subscriptions and profile | Customer self-service assistant with authenticated customer scope | Must preserve per-customer authorization and avoid cross-customer access |
| Licensing (Pro) | Licenses, keys, activations/sites, durations/status and package download | License support lookup, activation summaries, release/package checks | Key regeneration, deactivate, extend, and status writes affect entitlements |
| Roles/permissions (Pro) | Roles, assignments, managers and permissions | Permission audit and least-privilege explanation | Access-control changes are security-sensitive; human-only |
| Order bumps (Pro) | Bump CRUD, product/variant offers and checkout conditions | Cross-sell analysis and offer draft copy | Changes checkout conversion/price; approval and checkout QA required |
| Advanced inventory (Pro) | Inventory listing/stats/history, single/bulk adjustment, export | Stock alerts and reconciliation suggestions | Stock writes can oversell/understate stock; require trusted source and approval |
| Saved views (Pro) | Create/update/list/delete saved filters | Suggest useful operational views and report definitions | Low to moderate write risk; validate owner/team visibility |
| PDF templates (edition/add-on dependent) | Template and seller detail management, preview | Draft layout/copy and QA | Seller identity and legally meaningful invoice/receipt fields require human approval |
| Dashboard/activity | Stats, widgets, countries, activities, notes, pages, backfills | Summaries and support context | Page creation, backfills, and notes may mutate state |
Authentication, permissions, and operational behavior
Authentication
For the admin API, FluentCart documents WordPress Application Passwords over HTTP Basic Auth. The customer profile API uses WordPress cookie authentication with a REST nonce. Some public shop/checkout endpoints are unauthenticated. Cloudflare Access is a separate outer gate: passing Cloudflare Access does not authenticate the request to WordPress or grant FluentCart permissions.
Use HTTPS and a dedicated integration identity/application password. Do not use an admin's normal password. Store the secret server-side, redact authorization headers, and rotate/revoke the password on exposure or retirement. Do not put it in model context, shell history, source control, a browser playground, or logs.
Authorization
Admin routes apply FluentCart policy checks and granular permissions, for example:
- Product reads:
products/view - Product create:
products/create - Product update/pricing:
products/edit - Product deletion:
products/delete - Order reads:
orders/view; refunds:orders/can_refund - Coupon changes:
coupons/manage - Store configuration:
store/settingsand potentially super-admin/sensitive permissions
The live 401 response confirms the unauthenticated boundary is enforced. It does not prove permission-specific behavior for an authenticated low-privilege role. Test that role using a disposable, dedicated integration identity before production use.
Creating an Application Password without wp-admin
The WP-CLI command exists on opshell.dev (wp help user application-password was checked read-only). On the host, from the WordPress root, an operator can create one without opening the dashboard:
cd /home/wp_opshell_dev/sites/opshell.dev
wp user application-password create <user-id-or-login> "FluentCart AI integration" --porcelain
WordPress prints the new password once. Capture it directly into an approved secret manager or protected credential file; do not paste it into an AI prompt, this documentation, shell history, or logs. The UUID can be obtained from the command's creation output (or recorded safely by the credential manager). Revoke with:
wp user application-password delete <user-id-or-login> <application-password-uuid>
Opshell integration identity and enforced limits
After verifying that the only existing WordPress account was an administrator, a dedicated subscriber account was created and assigned a custom FluentCart role. The role is registered by wp-content/mu-plugins/opshell-fluentcart-ai-product-author.php (source is kept in the opshell project repository under mu-plugins/). It grants only products/view, products/create, and products/edit; it does not grant FluentCart delete, order, refund, customer, subscription, license, coupon, report, integration, or settings permissions.
Because product-level create/edit permission alone would otherwise allow broader product operations, the MU-plugin also enforces a fail-closed REST allowlist for this identity:
GET /fluent-cart/v2/products,GET /products/{id}, andGET /products/{id}/pricingare allowed.POST /fluent-cart/v2/productsis allowed only whenpost_statusis absent (FluentCart's documented draft default) or explicitlydraft.POST /fluent-cart/v2/products/{id}/pricingis allowed only for a draft product authored by this integration user, and only when status is absent ordraft.- Other FluentCart REST routes/methods, including product deletion/bulk actions, are denied.
The Application Password is stored outside the source/docs repository in a mode-600 local environment file. Its exact local path and variable names are recorded in the private aio-29 task record so an authorized local AI process can load it without exposing the secret in published documentation. Only processes running in the authorized local environment can read that file. Cloudflare Access is IP-gated separately; other AI machines need their own explicitly approved access path.
The password's owner and current REST boundary were tested: product list is allowed, orders are denied, and a publish attempt is blocked. No valid product-create request was made. Review the MU-plugin before extending its endpoint allowlist; changes to this security boundary affect the live store.
Live site permission finding: the only WordPress account found in the read-only user listing was admin with the administrator role. FluentCart's installed PermissionManager.php grants WordPress administrators all FluentCart permissions. For non-administrators, the installed built-in FluentCart roles include:
worker: product view but not product create/edit.manager: product view/create/edit, but also broad access including store settings, customer management/deletion, order management/refunds/deletion, subscription management/deletion, license management/deletion, coupons, reports, and integrations.accountant: read-oriented permissions; no product create/edit.
Therefore, simply creating a low-privilege WordPress user and Application Password is not enough for AI product creation. Assigning the built-in Manager role would be much broader than the intended product-only permission. A genuinely least-privilege product-authoring identity needs a reviewed custom FluentCart role/permission extension (the role registry exposes a filter) or an equivalent narrow server-side wrapper that safely limits what the integration identity can do. No WordPress user or Application Password was created during this research.
Data and response conventions
- The REST overview documents money in integer cents for API amounts (
$10.00→1000). Public product filter input may use decimal values in documented filtering options; do not assume every field shares one representation. - Documented timestamps use UTC/GMT; normalize/store timezone explicitly in reporting workflows.
- Pagination generally uses
pageandper_page; public shop additionally documents cursor-based pagination. - Documented errors include
400validation,401/403authentication/permission,404missing resource,422business-rule rejection, and429rate limit. Exact behavior can vary by endpoint. - Checkout documents a rate limit of five requests per 60 seconds per IP/user for order placement. Avoid high-volume AI loops; implement bounded retries and exponential backoff for retryable responses only.
- A 2xx response alone is insufficient evidence of success for a financial or commerce action. Check the response status/body, then read the resulting object back and reconcile expected fields.
Product API: safe conceptual workflow
Endpoints
The product API documents these relevant operations:
GET /products— admin catalog list/filter; requiresproducts/view.GET /products/{product}— admin product detail; can eager-load details and variants.POST /products— create product; documented example usespost_status: "draft"anddetail.fulfillment_type: "digital". A default variation is created automatically.POST /products/{postId}/pricing— save product pricing/details/variants; requires product edit permission.- Variation operations — list/create/update/delete variations and pricing tables.
- Product subresources — media, downloadable files, inventory, categories/terms, bundles, tax/shipping classes, integrations and upgrade paths.
This is a multi-step domain workflow. Creating the top-level product does not necessarily set final price, variation structure, downloadable asset, tax/shipping behavior, license configuration, or integration feed. Use the installed route/schema and test one operation at a time on staging.
Illustrative create-draft request
This is a documentation-shaped example, not a request sent to opshell.dev. Confirm exact body fields against the installed 1.7.0 operation schema before use.
curl --fail-with-body -sS \
-u "$FLUENTCART_USER:$FLUENTCART_APP_PASSWORD" \
-H 'Content-Type: application/json' \
-H 'Accept: application/json' \
-X POST 'https://opshell.dev/wp-json/fluent-cart/v2/products' \
--data '{
"post_title": "Approved product title",
"post_status": "draft",
"detail": { "fulfillment_type": "digital" }
}'
Never interpolate a model-generated URL/method/command. In a production integration, code owns the fixed base URL, fixed endpoint, allowed fields, status, and HTTP method; AI supplies only validated data. Avoid curl -k, credentials in command-line arguments/history, and printing verbose request headers. Prefer a secret manager or a protected credential file/HTTP client.
Product create strategy for AI
- AI converts a merchant-supplied brief into a strict JSON proposal. It cannot invent price, rights, availability, tax, shipping, refunds, or renewal promises.
- Deterministic validation enforces schema, currency, integer minor-unit arithmetic, allowed fulfillment type, title lengths, unique SKUs, safe asset references, and draft status.
- Human reviews a preview with exact amount, billing recurrence, variation, files, fulfillment, tax/shipping assumptions, and legal copy.
- A restricted integration creates the product draft with the dedicated API identity.
- The integration stores proposal/request ID and returned FluentCart product ID; before retrying a timeout, it searches/reads for a matching external proposal ID to prevent duplicates.
- Read the created product, pricing and variants back; compare with approved JSON and show mismatches.
- Human checks the product in wp-admin, validates the storefront/checkout on staging or Sandbox, and separately authorizes publication.
Do not assume a documented idempotency key exists for product creation. Implement safe client-side deduplication and never blindly retry a create after an ambiguous timeout.
AI-friendly route boundaries
Good candidates for read-only AI
- Public product search/catalog Q&A (no secret required, public data only).
- Authenticated admin product/catalog inspection using
products/view. - Read-only reports, order/customer/subscription summaries with minimum necessary fields and an approved privacy policy.
- Configuration completeness checks where only non-sensitive read fields are returned.
- Product proposal validation and mapping without API writes.
Approval-gated writes
- Create product draft (after human review of proposal); update product copy/metadata; create/update variations and assets.
- Coupon, order-bump and product integration creation/activation.
- Stock changes, order status changes, address changes, subscription changes, license operations, email template/notification settings.
Keep human-only or disabled for autonomous AI
- Publish/delete products and bulk destructive operations.
- Refunds, captures, marking an order paid, charging a subscription, creating a paid checkout order, payment-method switching, and any real-money action.
- Payment gateway credentials, live activation, tax/legal settings, user/role/permission changes, storage credentials, license key regeneration, and bulk customer/order exports.
Risks and control design
- Overbroad API credentials: no role should expose every admin endpoint to the model. Use separate identities for read-only reporting and draft creation if possible.
- REST is not inherently safe because it is structured: it includes DELETE, bulk, refund, checkout, charge, role, credential/configuration, upload, and licensing operations.
- Prompt injection and untrusted data: product descriptions, customer messages, order notes, files, and third-party web content can contain instructions. Treat them as data, never as authority to change allowed tools.
- Sensitive data disclosure: filter PII, addresses, transaction IDs, license keys, and file URLs before sending to an external model. Set retention and provider controls.
- Financial arithmetic: use integer cents and deterministic calculations; have humans define price, discount and subscription schedule.
- Retries and duplicate effects: GET is generally safe; POST can create records, orders, uploads, or messages. Use an idempotency/deduplication strategy, especially after timeouts.
- Inconsistent states: creation spans product, variation, file, tax, integration and license resources. Read back and reconcile after every step; maintain a state machine for partial failure and manual recovery.
- Access-layer bypass: CFPA bypasses Cloudflare Access for the current public IP; it does not grant WordPress API permissions. Keep the bypass limited to the exact app and maintain current IP scope. Do not expose the Access or WordPress token to AI.
- Route drift/version drift: the live REST root should be used to discover routes and operation schemas must be checked after plugin updates. Do not hard-code undocumented route behavior.
- No blind sandbox claim: a WordPress staging site and a payment provider Sandbox are separate environments. A draft create test does not verify payment checkout or actual entitlement delivery.
Recommended next test plan
Phase A — Authenticated read-only test
- Create or designate a dedicated WordPress integration account with only
products/view(and, if needed, separately approved report-read rights). Don't use a full admin account. - Create one application password, deliver it securely to the test client without committing or echoing it.
- Make
GET /wp-json/fluent-cart/v2/products?per_page=1over HTTPS; verify 200 JSON and expected pagination shape; redact titles/customer data in test logs. - Verify a deliberately underprivileged identity is denied on a protected route; do not test denial by attempting a destructive action.
- Revoke the test password after testing if it is not to become the permanent integration credential.
Phase B — Staging write test
- Use staging, backup first, and ensure the payment gateway is Sandbox or disabled.
- Create one uniquely named draft product with the smallest valid create body. Capture product/variation IDs.
- Read product and pricing back; test one price and one variation update using exact operation schemas.
- Test validation failures with a staging-only invalid payload; confirm no partial record remains or define manual recovery.
- Test timeout/deduplication; verify no duplicates. Clean up the test draft only on staging, using documented delete behavior after verifying exact ID.
- Do not test checkout, charge, refund, or live gateway actions as part of product CRUD verification.
Phase C — Restricted AI wrapper
Expose only a narrow tool set such as search_products, get_product, validate_product_proposal, create_product_draft, and read_back_product. The wrapper owns authorization, payload schema, fixed routes, logs, rate limits and dedupe. Require an explicit human approval token for the create call and reserve publish/delete/payment tools for a separately approved human-operated path.
Documentation and test evidence
- FluentCart REST API overview
- Products API
- Create Product operation
- Product pricing update
- Create Variation operation
- Public Shop API
- API Authentication and policies
- Checkout API and rate-limit example
- Local WP-CLI usage notes and AI product automation research.
Conclusion
The live FluentCart REST surface is present and discoverable on opshell.dev, and its public catalog endpoint responds correctly. Administrative reads correctly reject anonymous requests. This is enough to establish route reachability and the authentication boundary, but not enough to validate authenticated product reads or writes. The recommended next step is a dedicated least-privilege application password for read testing, followed by a staging-only draft-create test. No product or other commerce object should be written to production as an exploratory test.