Skip to content

Troubleshooting: 404 Not Found (Anti-Enumeration) ​

Some org-scoped services intentionally return 404 not-found when the caller is not associated with the org, even if the org or record exists. This hides tenant existence from unrelated callers (anti-enumeration). A 404 can therefore mean either "doesn't exist" or "you aren't allowed to know it exists."

This page helps you tell those cases apart.

WAF 403 (no JSON body) ​

If you receive a 403 response with an HTML body (not JSON), the request was blocked by the Web Application Firewall before reaching the application. Common causes:

  • Request body contains patterns matching known attack signatures (SQL fragments, <script> tags, ${jndi:...}, ../ path traversal).
  • Source IP is on the AWS IP Reputation blocklist.
  • Source IP exceeded 2,000 requests in 5 minutes (WAF rate limit).

Resolution: Inspect your request payload for suspicious patterns. Free-text fields (product descriptions, comments) with HTML-like content can trigger the Common Rule Set. If you believe it's a false positive, contact support with the request timestamp and source IP.

How to tell WAF 403 from app 403: Application 403 always has a JSON body with error.major.tag. WAF 403 has an HTML body and no error object.

Quick checklist ​

  • Use the custom domain: https://api.g3nretailstack.com/<service>/... (avoid execute-api URLs).
  • Confirm auth is valid: session is active (or API key is active) and sent in the correct place (headers for GET; JSON body for POST unless the service says otherwise).
  • Confirm org association: the session or API key must belong to the org you're querying.
  • Confirm orgcode: typos in orgcode are the most common 404 cause.
  • Confirm ID vs code: many endpoints accept either *_id or code. Passing a code where an ID is required returns 404.
  • GET semantics: GET parameters go in the query string. JSON bodies are ignored on GET.
  • Treat 404 as ambiguous: it can mean not found or not associated. Run the self-check flow before assuming absence.

Copy-paste checks ​

1) Validate your credential (401 vs 404) ​

Session (human)

sh
curl -sS -X POST https://api.g3nretailstack.com/usm/session/validate \
  -H 'Content-Type: application/json' \
  -d '{"session_guid":"SESSION_GUID","reason":"debug"}'
  • 401 means the session is invalid/expired/suspended.
  • 200 means the session is valid; move on to org association.

API key (service account)

sh
curl -sS -X POST https://api.g3nretailstack.com/usm/api_key/validate \
  -H 'Content-Type: application/json' \
  -H 'x-api-key: API_KEY' \
  -d '{"actor":"debug","reason":"debug"}'
  • 401 means the API key is invalid/expired/revoked.
  • 200 means the API key is valid; move on to org association.

2) Confirm org association (anti-enumeration check) ​

Session (human)

sh
curl -sS -X POST https://api.g3nretailstack.com/ofm/member/resolve \
  -H 'Content-Type: application/json' \
  -H 'x-session-guid: SESSION_GUID' \
  -d '{"orgcode":"ORGCODE"}'
  • 200 means the session is associated (owner or member) and returns roles.
  • 404 not-found means you are not associated with that org (anti-enumeration).

API key (service account)

sh
curl -sS -X POST https://api.g3nretailstack.com/ofm/member/resolve \
  -H 'Content-Type: application/json' \
  -H 'x-api-key: API_KEY' \
  -d '{"orgcode":"ORGCODE"}'
  • 200 means the API key is associated (owner or role-bearing service account).
  • 404 not-found means you are not associated with that org (anti-enumeration).

3) Confirm org status for writes (403 org-write-blocked) ​

Many writes require org.status=verified. If writes fail with 403 (org-write-blocked), the org must be verified by an operator.

Interpreting 401 vs 403 vs 404 ​

  • 401 Unauthorized: session invalid/expired or API key invalid/expired.
  • 403 Forbidden: you are associated but lack the required role, or the org is in a write-blocked status.
  • 404 Not Found: resource truly missing or you are not associated (anti-enumeration).

Service-level anti-enumeration matrix (current) ​

ServiceNon-associated callerNotes
UAS401 on invalid credentials/uas/stat hides existence by design.
USM401/403Session/API-key validation failures are 401.
OFM404Org-scoped operations return 404 when not associated.
MRS404Org-scoped records are hidden for non-associated callers.
PVM404Org-scoped product records are hidden for non-associated callers.
PMC404Published product records are hidden for non-associated callers.
ICS404Inventory records are hidden for non-associated callers.
SCM404Orders and fulfillment records are hidden for non-associated callers.
PCM404Procurement records are hidden for non-associated callers.
PPM404Pricing/promotion records are hidden for non-associated callers.
CRM404Customer records are hidden for non-associated callers.
Influencer404Attribution/earnings records are hidden for non-associated callers.
Accounting404Financial exports are hidden for non-associated callers.
IPM404Integration plane resources are hidden for non-associated callers.
RBS404Subscriptions are hidden for non-associated callers.
UTL404Offboarding/export resources are hidden for non-associated callers.
OPSRoot-onlyAll operations require root auth (scrypt secret). No session-based access.
UCP404Triple auth model (admin/platform/bearer). Non-associated callers see 404.
SLC404Action-dispatch model. Org-scoped channels hidden for non-associated callers.
VisualGridRoot-onlyAll operations require root auth (scrypt secret). No session-based access.

If a service behaves differently, it will document the exception on its Surfaces page.

Common 404 causes (beyond anti-enumeration) ​

  • Wrong resource type: style_id vs variant_id, org_guid vs orgcode.
  • Wrong channel selector: missing channel_guid/channel_code in PMC queries.
  • Wrong status: some list endpoints default to status=active and hide inactive/doomed records.
  • Typos in codes: codes are case-sensitive in most places; check canonicalization rules on each service page.

When you need to prove existence ​

Use an owner session for the org or an operator-only direct Lambda (where applicable). Owner sessions can disambiguate "not found" vs "not associated."

See also: