Business operations API
The business operations API provides companies, commercial links, purchases, personnel assignments, leads, opportunities, tasks, usage records, sales reports, and audit summaries for building your own back office.
Enable the required permissions under APIs and permissions → User identity → AppMarket Business Operations. For order endpoints, see Order management.
Setup
- Delivered company and sales features are available in your own application scope. Your current duties and data scope are checked on every request.
- Configure the required Scopes. Copy the Base URL, Application ID and API Product ID, and explicitly select the environment. The platform derives the Client and Audience from the effective configuration.
- Sign in with this application’s user OAuth authorization code + PKCE. Follow user authorization to confirm consent bound to the same application, environment, API product and Scopes. Use
{"resource_type":"appmarket_product","resource_ids":["your-product"]}. - Call from your own server. Each request supplies one
Authorization: Bearer <userToken>,X-GV-Organization-ID(provider organization),X-GV-Application-ID,X-GV-Environment,X-GV-API-Product-ID,X-GV-Delegated-Grant-ID, andX-GV-Product-Code. Selectsandbox|productionexplicitly; the platform derives the Client and binding.
Callers need valid organization membership, an application management relationship and the relevant company, commercial, purchase or sales permissions. Application owners use their existing operations access; other members need explicitly assigned duties.
Scopes, capability activation and consent are checked separately and do not replace business permissions. This product supports user tokens only. Administrator sales logs also require lead and opportunity management duties.
Published products appear in the catalog without manual registration. Each application still needs the actual API permissions and the user’s consent.
Operations and scopes
Companies and purchases
| Method and path | Scope |
|---|---|
GET /open-platform/v1/appmarket/companies:context | operations.company.read |
GET /open-platform/v1/appmarket/companies | operations.company.read |
GET /open-platform/v1/appmarket/companies/{company_id} | operations.company.read |
POST /open-platform/v1/appmarket/companies | operations.company.manage |
PATCH /open-platform/v1/appmarket/companies/{company_id} | operations.company.manage |
POST /open-platform/v1/appmarket/companies/{company_id}/{transition} | operations.company.manage |
GET /open-platform/v1/appmarket/companies/{company_id}/commercial-parties | operations.company.commercial.read |
GET /open-platform/v1/appmarket/companies/{company_id}/commercial-link | operations.company.commercial.read |
POST /open-platform/v1/appmarket/companies/{company_id}/commercial-link | operations.company.commercial.manage |
POST /open-platform/v1/appmarket/companies/{company_id}/commercial-link/unlink | operations.company.commercial.manage |
GET /open-platform/v1/appmarket/companies/{company_id}/purchases | operations.purchase.read |
Sales leads
| Method and path | Scope |
|---|---|
GET /open-platform/v1/appmarket/sales:context | operations.lead.read |
GET /open-platform/v1/appmarket/leads | operations.lead.read |
GET /open-platform/v1/appmarket/leads/{sales_id} | operations.lead.read |
GET /open-platform/v1/appmarket/leads/{sales_id}/followups | operations.lead.read |
POST /open-platform/v1/appmarket/leads | operations.lead.manage |
PATCH /open-platform/v1/appmarket/leads/{sales_id} | operations.lead.manage |
POST /open-platform/v1/appmarket/leads/{sales_id}/assign | operations.lead.manage |
POST /open-platform/v1/appmarket/leads/{sales_id}/reopen | operations.lead.manage |
POST /open-platform/v1/appmarket/leads/{sales_id}/duplicate | operations.lead.manage |
POST /open-platform/v1/appmarket/leads/{sales_id}/followup | operations.lead.manage |
POST /open-platform/v1/appmarket/leads/{sales_id}/qualify | operations.lead.manage |
POST /open-platform/v1/appmarket/leads/{sales_id}/disqualify | operations.lead.manage |
POST /open-platform/v1/appmarket/leads/{sales_id}/convert | operations.lead.manage |
Sales opportunities
| Method and path | Scope |
|---|---|
GET /open-platform/v1/appmarket/opportunities | operations.opportunity.read |
GET /open-platform/v1/appmarket/opportunities/{sales_id} | operations.opportunity.read |
PATCH /open-platform/v1/appmarket/opportunities/{sales_id} | operations.opportunity.manage |
POST /open-platform/v1/appmarket/opportunities/{sales_id}/assign | operations.opportunity.manage |
POST /open-platform/v1/appmarket/opportunities/{sales_id}/stage | operations.opportunity.manage |
POST /open-platform/v1/appmarket/opportunities/{sales_id}/reopen | operations.opportunity.manage |
Sales reports and logs
| Method and path | Scope |
|---|---|
GET /open-platform/v1/appmarket/sales-report | operations.sales.report.read |
GET /open-platform/v1/appmarket/sales-audits | operations.sales.audit.read |
Webhook deliveries
| Method and path | Scope |
|---|---|
GET /open-platform/v1/appmarket/webhook-deliveries | operations.event.read |
Customer personnel and seats
| Method and path | Scope |
|---|---|
GET /open-platform/v1/appmarket/companies/{company_id}/users | operations.user.read |
PUT /open-platform/v1/appmarket/companies/{company_id}/users/{membership_id}/assignment | operations.user.assign |
Subscription usage
| Method and path | Scope |
|---|---|
GET /open-platform/v1/appmarket/subscription-usage:context | operations.usage.read |
GET /open-platform/v1/appmarket/subscription-usage | operations.usage.read |
POST /open-platform/v1/appmarket/subscription-usage | operations.usage.record |
Commercial tasks
| Method and path | Scope |
|---|---|
GET /open-platform/v1/appmarket/tasks | operations.opportunity.read |
GET /open-platform/v1/appmarket/tasks/{sales_id} | operations.opportunity.read |
GET /open-platform/v1/appmarket/tasks/{sales_id}/history | operations.opportunity.read |
POST /open-platform/v1/appmarket/tasks | operations.opportunity.manage |
PATCH /open-platform/v1/appmarket/tasks/{sales_id} | operations.opportunity.manage |
POST /open-platform/v1/appmarket/tasks/{sales_id}/assign | operations.opportunity.manage |
POST /open-platform/v1/appmarket/tasks/{sales_id}/start | operations.opportunity.manage |
POST /open-platform/v1/appmarket/tasks/{sales_id}/submit | operations.opportunity.manage |
POST /open-platform/v1/appmarket/tasks/{sales_id}/review | operations.opportunity.manage |
POST /open-platform/v1/appmarket/tasks/{sales_id}/return | operations.opportunity.manage |
POST /open-platform/v1/appmarket/tasks/{sales_id}/cancel | operations.opportunity.manage |
POST /open-platform/v1/appmarket/tasks/{sales_id}/reopen | operations.opportunity.manage |
Quotations
| Method and path | Scope |
|---|---|
GET /open-platform/v1/appmarket/quotes:context | operations.opportunity.read |
GET /open-platform/v1/appmarket/quotes:options | operations.opportunity.read |
GET /open-platform/v1/appmarket/quotes | operations.opportunity.read |
POST /open-platform/v1/appmarket/quotes | operations.opportunity.manage |
GET /open-platform/v1/appmarket/quotes/{sales_id} | operations.opportunity.read |
PATCH /open-platform/v1/appmarket/quotes/{sales_id} | operations.opportunity.manage |
GET /open-platform/v1/appmarket/quotes/{sales_id}/history | operations.opportunity.read |
POST /open-platform/v1/appmarket/quotes/{sales_id}/submit | operations.opportunity.manage |
POST /open-platform/v1/appmarket/quotes/{sales_id}/approve | operations.opportunity.manage |
POST /open-platform/v1/appmarket/quotes/{sales_id}/return | operations.opportunity.manage |
POST /open-platform/v1/appmarket/quotes/{sales_id}/send | operations.opportunity.manage |
POST /open-platform/v1/appmarket/quotes/{sales_id}/withdraw | operations.opportunity.manage |
POST /open-platform/v1/appmarket/quotes/{sales_id}/revise | operations.opportunity.manage |
POST /open-platform/v1/appmarket/quotes/{sales_id}/expire | operations.opportunity.manage |
Write requests and retries
- Request read scopes separately;
managedoes not include them. Lead conversion also requires opportunity management duties. - Use
stageto record won or lost opportunities. Check payment and revenue separately. - Company
{transition}accepts onlyarchiveandrestore. - Ordinary writes, including PATCH, require the original
Idempotency-Key, current resource version and reason specified by the API. - Subscription usage uses
event_idfor deduplication and needs no extra request key or resource version.
After interruption or 503, retain the original key, body and version. Usage reporting retains the original event ID and body. On 409, inspect the original record before deciding what to do; do not automatically change its event ID or version.
Queries and operations
Create quotations
Open Customer operations → Quotations. Callers need opportunity read/manage, company read and commercial read access.
Create or edit with the current opportunity and version, company, offer and version, plan, quantity (1–1000000), deadline, name, resource_version and reason. Query available offers through quotes:options with opportunity_id, opportunity_version and company_id.
Published fixed-price offers determine prices, totals, tax rules and full terms. Requests do not accept custom prices, discounts or terms.
Quotations follow draft → review_pending → approved → sent → accepted/declined, with withdrawn/expired alternatives.
| Action | Meaning |
|---|---|
submit | Request review |
approve | Approve with approval_evidence_ref |
return | Return to draft |
send | Allow customers to read and decide through the customer quotation API; no email is sent |
revise | Create a new revision of a sent, declined, withdrawn or expired quotation, clearing review and send information |
Drafts are editable; accepted quotations cannot change. Expiry blocks sending and new acceptance even before expire runs. Customers must accept or decline themselves. A decision records that version's outcome; ordering, payment and product activation are separate steps.
Recover unknown results with the original Idempotency-Key, body and version, then GET the current quotation. After 409, read again and confirm a new request.
Lists support search/status/limit/cursor; history supports limit/cursor, both in ID order. Cursors apply only to the original scope and parent quotation. History retains full quotation snapshots, actors, reasons, revisions and review evidence. New drafts preserve previously sent terms.
Manage commercial tasks
Open Customer operations → Commercial tasks with lead and opportunity management enabled and opportunity read/manage duties.
Create with opportunity_id, current source_version, name, instructions, business owner_ref, UTC due_date, resource_version: 0 and reason. The owner reference records a business assignee without establishing membership or granting access.
Tasks record work for that opportunity. Orders, payments, activation, entitlements and support require separate operations.
Tasks follow open → working → review_pending → closed:
| Action | Meaning |
|---|---|
start | Start work |
submit | Submit evidence_ref |
review | Review and close |
return | Return to work |
cancel | Cancel an unclosed task |
reopen | Reopen a closed or cancelled task |
Only open or working tasks allow editing and assignment. Include the current resource_version, reason and original Idempotency-Key. After 409, read the task or source again and confirm. After 503, recover with the original body, version and key, then GET the current task; the recovered receipt may describe an earlier state.
Task lists support search, status, limit (1–100, default 50) and cursor, ordered by task ID. History uses limit and cursor, ordered by entry ID, and includes actions, task versions, actor references, reasons, evidence references and timestamps.
Keep filters and cursors unchanged. Cursors bind the original application, product, environment and parent task; do not parse or reuse them across tasks. Display errors in the current scope when an object is missing or denied. These endpoints provide opportunity tasks and their history.
Query subscription usage
Open Business insights → Subscription usage with the current sign-in and customer operations capability. Application owners can read and report their application's usage; collaborators need the relevant duties. These APIs do not return customer personnel or financial details.
| Parameter or field | Required | Meaning |
|---|---|---|
from, to | 🔴 Required | RFC3339; inclusive start, exclusive end, at most 366 days |
subscription_id, customer_organization_id, metric, status | Optional | Omit for no corresponding filter |
limit | Optional | 1–100, default 50 |
offset | Optional | 0–1000000, default 0 |
summary, metrics, trend | Response only | Cover all matching events; UTC trends include observed days only |
Select View usage records on a subscription in Commerce → Purchases, company purchase history or order details. The panel shows that subscription's statistics and events without copying its ID. It defaults to 30 days; dates, customer, metric and outcome are editable, while the subscription stays fixed. Paused or cancelled subscriptions can show accepted history.
Usage access is checked separately. Query failures preserve the purchase or order page. A 403 clears usage; select Recheck usage access before querying again. Refreshing the original purchase or order closes the panel. One-time orders have no usage entry.
View monthly statistics
Select Read monthly usage statistics under Business home → This month's subscription usage. After access checks, the panel shows events, outcomes, customer/subscription counts, reported product users and daily trends from the UTC month's first day through today, inclusive.
Keep metrics and units separate. Product user references cannot measure authorized members. Statistics cover the full period. Custom backends can use limit=1&offset=0 to get summary, metrics and trend without reading every event page.
Refresh monthly statistics checks access and updates to the current UTC month. After 503, Retry original statistics window preserves the original dates even across a month change.
401/403 clears results and stops queries until Recheck usage access. Closing the panel or changing application, organization, environment, access or language clears results. Usage failures leave sales available. View all usage records opens date and condition filters. Query charges, balances and received payments separately.
Report usage
Submit the original event_id, customer organization and subscription IDs, occurred_at, metric, unit, actual integer quantity, status (succeeded|failed|cancelled) and user_reference.
user_reference can be empty or an application-local anonymous reference using letters, digits, underscores and hyphens. Do not send email, names, tokens or content. It does not establish platform membership. Include duration_ms only if measured.
The platform verifies seller and customer subscription and records their plan, price and period. Requests cannot override these values. The first event must fall in a currently usable subscription period; late events outside it return 409. Historical corrections are unavailable. Identical events can recover their receipt after renewal or cancellation; changed content returns 409. event_id provides idempotency without a resource version or extra key.
Use exact integer strings for quantities, grouped by metric + unit. Do not convert to JavaScript Number, add different units, or display quantities as money or Token balances. Reporting does not create charges, balances or user authorization.
After query 503, keep the original filters. After reporting 503, resend the original event ID and body. Clear old records after 403.
Read customer personnel and assign seats
The company must have an active customer organization link and explicit consent for this product. A customer owner or administrator can authorize the provider to read names, statuses and purchase assignments. Seat changes require the separate assignment option. Commercial links, payments and application ownership do not replace personnel authorization. Responses omit email, phone, account management and financial data.
Queries support limit (1–100), offset, literal name search and assigned_only. can_use indicates current product eligibility.
Assignments require the current subscription, version, explicit assigned and original request key. Revocation, expiry, suspended personnel or subscription replacement rejects later queries, changes and retries. Preserve unknown results and recover the original request before further operations.
View company details
Read companies/{company_id}, companies/{company_id}/commercial-link and companies/{company_id}/purchases as needed. Each requires its own scope and duties from the table.
Companies → View details loads the selected tab's section. A section's 403 clears it and rechecks company access. Other sections remain if company details are readable; otherwise return to the directory. Company refresh 503 removes old details and offers a retry. Recover uncertain commercial writes before switching sections.
Paginate lists
Keep filters unchanged and return next_cursor exactly as received. Do not parse it. Loaded company, lead and opportunity counts describe current page data. Clear results and restart from the first page after changing organization, application, environment, permissions or filters.
Sales reports
Supply from and to as inclusive UTC dates in YYYY-MM-DD, at most 366 days apart. Reports count the current state of every record created in that window. Historical stage changes require a separate query.
as_of is report generation time; source_updated_at is the latest source update and is empty for an empty report. Group open-opportunity estimates by currency and scale. Keep minor_units as an exact integer string rather than JavaScript Number. Estimates describe sales forecasts; query revenue, received payments and order totals separately.
Sales operation logs
Use the same date parameters as sales reports. limit is 1–100 (default 50); optional target_type is appmarket_lead, appmarket_opportunity or appmarket_lead_followup.
Records descend by occurrence time and ID. Cursors bind application scope, dates and type. Responses include actor references, actions, target references, results, request trace IDs and timestamps, without bodies or reasons. Other administrator logs are unavailable.
Webhook delivery history
Query webhook-deliveries as a current application owner or manager with webhook.read. Company and sales capabilities are not required.
| Parameter | Required | Meaning |
|---|---|---|
limit | Optional | 1–200, default 50 |
status, event_type | Optional | Status or exact event type; omit for no corresponding filter |
search | Optional | Literal substring in event type, event ID or delivery ID; omit for no search filter |
from, to | Optional | RFC3339, inclusive start, exclusive end; omit for no corresponding time bound |
cursor | Optional | Omit for the first page; pass next_cursor unchanged for the next page |
Filters cover all retained history before server pagination. Records descend by creation time, then ascend by delivery ID for equal times. Keep the query and next_cursor unchanged; the last page omits the cursor. Refresh the first page for new records. Status reflects query time. Unknown or cross-application cursors return 400.
Console dates cover complete UTC days. Next-page 503 preserves loaded records and cursor; 403 clears history. Responses exclude payloads, headers and credentials. The API provides delivery history, without a complete business-event archive or replay permission.
Errors and recovery
All responses use Cache-Control: no-store.
| Status | Action |
|---|---|
400/422 | Correct invalid or repeated parameters |
401 | Restore the current user session |
403 | Clear data and recheck capabilities, scopes, consent and duties |
404 | Display the error for the current scope; do not try another application ID |
409 | Read the latest resource and confirm the operation |
429 | Wait for Retry-After |
503 | Show temporary unavailability, not an empty list, zero statistic or successful write |
Clear old pages and query again when a company's purchase association changes.
See the business operations OpenAPI for fields and command bodies.