Order Management
Order management supports order queries, cancellation, and payment status checks. Use Developer Console → Commerce → Orders or build your own back office with the public API. Both follow the same business rules.
Orders are isolated by provider organization, Application, product, and environment. No customer company selection is required.
Enable and authorize
- Order management is available in your own application scope without a separate enable step. Open Commerce → Orders. If access is denied or disabled, check your current duties and application state.
- Under API and permissions, select the user identity and Order Management. Configure the required Scopes. Copy the Application ID, API Product ID and Base URL, and select the
sandbox|productionenvironment. The platform derives the Client and Audience from the effective configuration. - Sign in using that application's user OAuth authorization code with PKCE. The token must be issued for that user client and include the required Audience and Scope. Your own backend may keep its own user session and call this API.
- Select the provider enterprise and confirm person consent for
{"resource_type":"appmarket_product","resource_ids":["your-product"]}. Consent must bind the same Application, environment, API Product and Scopes, and remain unexpired and unrevoked. See User authorization.
This API supports user tokens only. Callers need valid organization membership and application management access. Owners can read this application's orders and cancel eligible orders. Other members need separately assigned order read or cancellation duties.
Capability configuration and API permissions do not grant access to other organizations' orders or financial execution rights.
| Scope | Permission |
|---|---|
operations.order.read | Read availability, list and details |
operations.order.cancel | Cancel eligible orders; does not include the read Scope |
operations.payment.read | Read original order payment evidence; requires the separate payment read duty |
Public endpoints
| Method and path | Scope | Result |
|---|---|---|
GET /open-platform/v1/appmarket/orders:context | operations.order.read | Capability availability, product, allowed actions and reason |
GET /open-platform/v1/appmarket/orders | operations.order.read | Bounded order page and next cursor |
GET /open-platform/v1/appmarket/orders/{order_id} | operations.order.read | Current order and allowed actions |
POST /open-platform/v1/appmarket/orders/{order_id}/cancel | operations.order.cancel | Original successful cancellation receipt |
GET /open-platform/v1/appmarket/orders:payment-context | operations.payment.read | Current payment read duty and allowed actions |
GET /open-platform/v1/appmarket/orders/{order_id}/payment | operations.payment.read | Linked payment status, amount, completed refund aggregate and timestamps |
Send these headers with exactly one value each:
| Header | Content |
|---|---|
Authorization: Bearer <user token> | Current application user token |
X-GV-Organization-ID | Provider organization |
X-GV-Application-ID | Current application |
X-GV-Environment | Explicit sandbox or production environment |
X-GV-API-Product-ID | API product for this operation |
X-GV-Delegated-Grant-ID | User consent |
X-GV-Product-Code | Current product |
The environment must match the grant and current application source. Internal environment bindings, target customers or ownership claims cannot expand access. Responses use Cache-Control: no-store.
Copy the current environment's Base URL and Audience from the Console. Never mix application or environment configuration. The values below are placeholders. Keep tokens out of code, logs and downloads.
const context = {
baseURL: `${process.env.GOODVISION_API_BASE}/open-platform/v1`, // environment-issued API Base URL, e.g. https://api.example.test
headers: {
Authorization: `Bearer ${process.env.ORDER_USER_TOKEN}`,
'X-GV-Organization-ID': process.env.ORDER_ORGANIZATION_ID,
'X-GV-Application-ID': process.env.ORDER_APPLICATION_ID,
'X-GV-Environment': process.env.ORDER_ENVIRONMENT,
'X-GV-API-Product-ID': process.env.ORDER_API_PRODUCT_ID,
'X-GV-Delegated-Grant-ID': process.env.ORDER_DELEGATED_GRANT_ID,
'X-GV-Product-Code': process.env.ORDER_PRODUCT_CODE,
},
};
const response = await fetch(`${context.baseURL}/appmarket/orders?limit=25&kind=one_time`, {
headers: context.headers,
cache: 'no-store',
});
if (!response.ok) throw new Error(`Order API returned ${response.status}`);
const page = await response.json();
// An empty page.next_cursor ends pagination.Filters and meaning
List parameters:
| Parameter | Required | Meaning |
|---|---|---|
limit | Optional | 1–100, default 25 |
search | Optional | Order number substring, at most 200 characters; omit for no search filter |
status | Optional | Omit for all authorized order statuses |
kind | Optional | subscription, one_time or token_package; omit for all kinds |
cursor | Optional | Omit for the first page; pass next_cursor unchanged for the next page |
Order statuses are draft, pending_approval, approved, awaiting_payment, paid, fulfilling, fulfilled, cancelled, payment_unknown, refund_pending and refunded.
Orders ascend by ID. Keep filters and next_cursor unchanged for the next page. Start from the first page after changing filters, organization, application, product or environment.
Do not parse cursors or combine pages from different scopes. Loaded counts describe current page data. Each page reflects state at query time; refresh orders that continue to change.
plan_code, plan_version, total, items and accepted_at describe the original purchase. Money consists of integer value, decimal scale and currency, for example 500 / 10² = USD 5.00. Preserve precision.
customer_organization_id identifies the purchasing customer without providing member details or management access.
Orders and current subscriptions have separate fields:
| Field | Meaning |
|---|---|
status | Commercial and delivery progress |
payment_status | Order payment summary: not_started, awaiting_payment, paid, refund_pending, refunded or unknown |
subscription_id, subscription_status | Current subscription and status |
current_plan_code and version | Current plan, which may differ from the purchased plan |
current_period_start, current_period_end | Current subscription period |
Without a subscription, these fields are empty and versions are 0. Check payment, delivery, member assignment and product eligibility separately.
Cancellation and recovery
Read the detail first. Only enable cancellation when its allowed_actions contains order.cancel. The current operation supports independent orders using the current safe payment flow before any payment starts. Subscription orders, Token packages, paid/in-flight/unknown payments and legacy orders requiring reconciliation cannot be cancelled here. Subscription lifecycle management uses the subscription API. Order cancellation does not refund or revoke product access.
const original = {
key: crypto.randomUUID(),
body: { resource_version: order.resource_version, reason: 'Customer cancelled this purchase' },
};
const response = await fetch(`${context.baseURL}/appmarket/orders/${order.id}/cancel`, {
method: 'POST',
headers: { ...context.headers, 'Content-Type': 'application/json', 'Idempotency-Key': original.key },
body: JSON.stringify(original.body),
});Cancellation cannot be undone. Payment start and cancellation check the same version. After one succeeds, the other cannot use the old version.
- Interruption or
503: keep the original order, version, reason andIdempotency-Key; recover with the same request. - Same key with a different body:
409. - Success: GET the details for current state; the receipt describes the original request.
- Version conflict
409: keep the reason, read the latest order, then ask the user to confirm a new version and key.
Do not retry cancellation automatically. The Console uses this flow too.
Errors
| HTTP | Recovery |
|---|---|
| 400/422 | Fix missing, repeated or invalid context/parameters. Details and cancellation accept no query parameters |
| 401 | Sign in with the current application's user identity |
| 403 | Capability, Scope, consent, membership, application relationship or order authority denied; clear old data and recheck |
| 404 | Order absent from the current scope; never try another customer identifier |
| 409 | Version/original request conflict, payment started or cancellation unavailable; reread and confirm explicitly |
| 429 | Wait for Retry-After; preserve the original request key |
| 503 | State or outcome is temporarily unavailable. Retry reads and recover cancellation with the original key; do not display an empty list or success |
Disabling order management hides its menu and rejects later business requests while preserving orders. Re-enabling reads current orders. Custom backends should clear orders and drafts on sign-out, revocation or organization/application/environment changes and ignore late responses from old requests.
See API products and the Order OpenAPI for complete fields and error structure.
Display names
Order responses may include customer_display_name and plan_display_name. Use the customer name and the original purchased plan name when available. Missing or empty names should display “Unnamed enterprise” and “Unnamed plan”. A current subscription's plan code describes the current plan and may differ from the original purchase. Keep identifiers in labeled details or copy controls; never infer a customer's identity from an ID.
Payment evidence inside an order
Click View payment evidence in order details to check the separate payment read duty with the current session. Your enterprise administrator assigns that duty through an existing role. Application ownership and order read authority do not grant payment evidence. Errors stay within the payment panel; explicitly recheck without signing in again.
| Result | Meaning |
|---|---|
availability=available | Linked payment's current status, exact scaled amount, completed refunds, payment version and creation/update timestamps |
not_linked | No linked payment order; this does not prove that no charge occurred |
| Query failure | Show the error without substituting an order payment summary |
Refund totals include completed refunds only. Query invoices, ledger revenue, settlement balances and access separately. This endpoint is read-only; it does not initiate payment, refunds or payment-provider status refreshes.