Appearance
Surfaces
Interactive API Explorer: Explorer
The authoritative surface is the OpenAPI spec:
/ppm/openapi.yaml
Surface Types (explicit)
API Gateway
- Status: Available.
- Base:
https://api.g3nretailstack.com/ppm - Notes: Primary tenant surface for pricing and promotions workflows.
Direct Lambda
- Status: Not offered.
- Notes: No direct Lambda surface is documented for PPM.
CLI
- Status: Available.
- Command:
g3n ppm ...(API Gateway). - Notes: See
cli/README.md.
MCP
- Status: Available.
- Canonical protocol:
https://mcp.g3nretailstack.com/ppm/PROTOCOL.md - Mirror:
https://doc.g3nretailstack.com/ppm/PROTOCOL.md
Auth + tenancy
- Required headers:
x-orgcodeandx-session-guid(user session) orx-api-key(org-bound service account). - Header auth is canonical; body auth is accepted where documented. See /common/headers-identity.html.
- Optional cost attribution:
x-cccode(or request fieldcccode) where supported; see OpenAPI. - Non-associated callers receive
404 not-found(anti-enumeration). - Facility context:
x-logical-guid(required for operational actions; see OpenAPI per-path).x-channel-code(required where documented; see OpenAPI per-path).
Identifier policy
- Direct get/update/status calls require GUID/ID fields (
*_idor legacy*_guidwhere that is the canonical field name). Code-based lookups are resolve/search only. - Responses never include both
*_idand*_guidfor the same record (no dual-field output). - Exceptions (email-based UAS, PVM resolve, MRS
container+record_id) are listed in /common/ids-codes.html.
Request builder (API Gateway)
Headers (canonical)
bash
-H "x-orgcode: $ORGCODE"
-H "x-session-guid: $SESSION_GUID" # or: -H "x-api-key: $API_KEY"
-H "content-type: application/json"Template
bash
curl -sS -X POST "https://api.g3nretailstack.com/ppm/<endpoint>" \
-H "content-type: application/json" \
-H "x-orgcode: $ORGCODE" \
-H "x-session-guid: $SESSION_GUID" \
-d '{"...": "..."}'Notes
- Replace
<endpoint>with a route from the OpenAPI inventory. - Header auth is canonical; body
session_guid/api_keyis accepted where documented.
Implemented surfaces now include:
- Price approvals:
/ppm/price/approval/* - Price lists:
/ppm/price-list/*(set/get/list/status + assign/clear/resolve/assignments) - Price zones:
/ppm/price-zone/*(set/get/list/status/assign/clear/resolve/assignments) - Price resolve uses
customer_refto auto-resolve a contract price list whenprice_list_codeis omitted. - Price recommendations:
/ppm/recommendation/*(set/get/list/status) - Commission rules:
/ppm/commission-rule/*(set/get/list/status/set) - Comments:
/ppm/comment|comment/get|comment/list|comment/revise|comment/status|comment/report - Inbox:
/ppm/inbox/create|get|list|status|state
Endpoint inventory (OpenAPI parity)
Request/response schema names reference OpenAPI component schemas.
| Method | Path | Request schema | Response schema |
|---|---|---|---|
| POST | /comment | CommentAddRequest | CommentEnvelope |
| POST | /comment/get | CommentGetRequest | CommentEnvelope |
| POST | /comment/list | CommentListRequest | CommentListEnvelope |
| POST | /comment/report | CommentReportRequest | CommentReportEnvelope |
| POST | /comment/revise | CommentReviseRequest | CommentEnvelope |
| POST | /comment/status | CommentStatusRequest | CommentEnvelope |
| POST | /dynamic-rule/get | DynamicPricingRuleGetRequest | DynamicPricingRuleEnvelope |
| POST | /dynamic-rule/list | DynamicPricingRuleListRequest | DynamicPricingRuleListEnvelope |
| POST | /dynamic-rule/set | DynamicPricingRuleSetRequest | DynamicPricingRuleEnvelope |
| POST | /dynamic-rule/status/set | DynamicPricingRuleStatusSetRequest | DynamicPricingRuleEnvelope |
| POST | /inbox/create | InboxCreateRequest | InboxEnvelope |
| POST | /inbox/get | InboxGetRequest | InboxEnvelope |
| POST | /inbox/list | InboxListRequest | InboxListEnvelope |
| POST | /inbox/state | InboxStateRequest | InboxEnvelope |
| POST | /inbox/status | InboxStatusRequest | InboxEnvelope |
| POST | /policy/get | PricePolicyGetRequest | PricePolicyEnvelope |
| POST | /policy/set | PricePolicySetRequest | PricePolicyEnvelope |
| POST | /price-list/assign | PriceListAssignRequest | PriceListAssignmentEnvelope |
| POST | /price-list/assign/clear | PriceListAssignClearRequest | PriceListAssignmentEnvelope |
| POST | /price-list/assignments | PriceListAssignmentsRequest | PriceListAssignmentListEnvelope |
| POST | /price-list/get | PriceListGetRequest | PriceListEnvelope |
| POST | /price-list/list | PriceListListRequest | PriceListListEnvelope |
| POST | /price-list/resolve | PriceListResolveRequest | PriceListAssignmentEnvelope |
| POST | /price-list/set | PriceListSetRequest | PriceListEnvelope |
| POST | /price-list/status/set | PriceListStatusSetRequest | PriceListEnvelope |
| POST | /price-zone/assign | PriceZoneAssignRequest | PriceZoneAssignmentEnvelope |
| POST | /price-zone/assign/clear | PriceZoneAssignClearRequest | PriceZoneAssignmentEnvelope |
| POST | /price-zone/assignments | PriceZoneAssignmentsRequest | PriceZoneAssignmentListEnvelope |
| POST | /price-zone/get | PriceZoneGetRequest | PriceZoneEnvelope |
| POST | /price-zone/list | PriceZoneListRequest | PriceZoneListEnvelope |
| POST | /price-zone/resolve | PriceZoneResolveRequest | PriceZoneAssignmentEnvelope |
| POST | /price-zone/set | PriceZoneSetRequest | PriceZoneEnvelope |
| POST | /price-zone/status/set | PriceZoneStatusSetRequest | PriceZoneEnvelope |
| POST | /price/approval/approve | PriceApprovalApproveRequest | PriceEntryEnvelope |
| POST | /price/approval/reject | PriceApprovalRejectRequest | PriceEntryEnvelope |
| POST | /price/approval/submit | PriceApprovalSubmitRequest | PriceEntryEnvelope |
| POST | /price/get | PriceEntryGetRequest | PriceEntryEnvelope |
| POST | /price/list | PriceEntryListRequest | PriceEntryListEnvelope |
| POST | /price/resolve | PriceResolveRequest | PriceResolveEnvelope |
| POST | /price/set | PriceEntrySetRequest | PriceEntryEnvelope |
| POST | /recommendation/get | PriceRecommendationGetRequest | PriceRecommendationEnvelope |
| POST | /recommendation/list | PriceRecommendationListRequest | PriceRecommendationListEnvelope |
| POST | /recommendation/set | PriceRecommendationSetRequest | PriceRecommendationEnvelope |
| POST | /recommendation/status/set | PriceRecommendationStatusSetRequest | PriceRecommendationEnvelope |
| POST | /promotion/create | PromotionCreateRequest | PromotionEnvelope |
| POST | /promotion/end | PromotionEndRequest | PromotionEnvelope |
| POST | /promotion/get | PromotionGetRequest | PromotionEnvelope |
| POST | /promotion/list | PromotionListRequest | PromotionListEnvelope |
| POST | /commission-rule/set | CommissionRuleSetRequest | Envelope |
| POST | /commission-rule/get | CommissionRuleGetRequest | Envelope |
| POST | /commission-rule/list | CommissionRuleListRequest | Envelope |
| POST | /commission-rule/status/set | CommissionRuleStatusSetRequest | Envelope |
| POST | /uom/get | UomConversionGetRequest | UomConversionEnvelope |
| POST | /uom/list | UomConversionListRequest | UomConversionListEnvelope |
| POST | /uom/set | UomConversionSetRequest | UomConversionEnvelope |
Error tags
Common tags (see /common/error-tags.html for definitions): validation-error, unauthorized, forbidden, not-found, expected-revision-required, conflict, invalid-state, throttled, internal-error.
Example envelopes
Success envelope (shape-only):
json
{
"success": true,
"data": { "example": "see schema for fields" },
"build": { "build_major": "MONDAY", "build_minor": "0000000000", "build_id": "MONDAY-0000000000" },
"stats": { "call": "example", "service": "ppm", "timestamp_utc": "2026-01-21T00:00:00Z" }
}Error envelope (shape-only):
json
{
"success": false,
"error": {
"error_code": "ppm.conflict_revision",
"http_status": 409,
"retryable": false,
"request_id": "req-123",
"trace_id": "trace-abc",
"major": { "tag": "conflict", "message": { "en_US": "Expected revision does not match the current record." } },
"details": { "expected_revision": "3", "current_revision": "4" },
"conflict_snapshot": { "revision": 4 }
},
"build": { "...": "..." },
"stats": { "call": "example", "service": "ppm", "timestamp_utc": "2026-01-21T00:00:00Z", "request_id": "req-123" }
}Role requirements (by endpoint family)
- Read/list/resolve:
ppm_view(or owner). - Price rule writes:
ppm_price_admin(or owner). - Commission rule writes:
ppm_price_admin(or owner). - Promo writes:
ppm_promo_admin(or owner). - Approvals:
ppm_approver/ppm_approve(or owner).
Idempotency & retries
- Use
expected_revisionfor updates to policies and promos. - Idempotent write endpoints accept
idempotency_key(ASCII <=128 chars). When supplied, the service replays the original response for 24h; replays with a different payload return 409idempotency-conflict. - Calls without a documented idempotency key are not idempotent.
Common pitfalls
- Price resolution requires
logical_guid+channel_codewhen facility/channel scoped. - Scheduled promotions respect timezone; ensure
effective_from/toare UTC. - Comment/inbox lists default to
status=current/status=inbox; usestatus=allto include archived/doomed.
Examples (core families)
Price resolve
json
{ "logical_guid": "LOGICAL_GUID", "channel_code": "WEB", "items": [{ "variant_id": "VARIANT_ID", "qty": 1 }], "reason": "cart" }Response (shape):
json
{ "success": true, "data": { "prices": [] }, "build": { "...": "..." }, "stats": { "...": "..." } }Promotion create
json
{ "promo": { "code": "SAVE10", "type": "percent", "value": 10 }, "reason": "launch" }Response (shape):
json
{ "success": true, "data": { "promo_id": "PROMO_ID" }, "build": { "...": "..." }, "stats": { "...": "..." } }