CommonQuant B2B sandbox API
Managed by CommonQuant. Fixed synthetic responses from the CommonQuant backend.
API origin: https://api.sandbox.commonquant.ai; route prefix: /api-sandbox. Sandbox UI and documentation: sandbox.commonquant.ai/api. Send integration requests from your server to the API host; the UI host does not accept credentialed API operations.
Free integration testing with deterministic dummy data. The sandbox uses the CommonQuant request and response schemas for the documented subset below. It never activates a paid license, consumes real credits or allowance, reads customer or market data, calls a paid provider, or changes production billing.
Download the supported CommonQuant OpenAPI contract. Check API health for the exact deployed release and transport: native_synthetic_fixture. Successful API responses carry X-CommonQuant-Mode: sandbox, X-CommonQuant-Data: synthetic and X-CommonQuant-Financial-Effects: none. Synthetic research is also labeled inside the existing content fields.
Integration guides (production calls with a sandbox quick-start): license API for the business server and using the API for a licensed member. Public, unauthenticated on this host: GET /health, GET /api-sandbox/ (this page), GET /api-sandbox/openapi.json and GET /api-sandbox/limits.
Access and isolation
Get started: sign up for a business account at partners.commonquant.ai, create a sandbox key there (no approval needed; production access is approved separately) and call https://api.sandbox.commonquant.ai. Your server sends the cq_sandbox_ key in X-CQ-Business-Key. Each business account is one isolated tenant shared by its sandbox keys; do not share keys between businesses. Browser Origin requests are refused. Sandbox keys cannot access production, and production keys cannot authenticate here. No paid CommonQuant license activation is needed. License-scoped calls additionally use the returned X-CQ-License-Secret and the matching opaque member UUID.
Key lifetime and reset. A key works until the expiry you chose when you created it (90 days by default, at most 365); then calls return 401 sandbox_key_expired and you create a new key in the portal. Revoking a key in the portal stops listing it, but because this environment serves only synthetic data a revoked key keeps working until its expiry. POST /api-sandbox/reset with your key clears your licenses, idempotency receipts and read counter, so you can start a test run from nothing at any time; other businesses are untouched. State is kept in memory, so a sandbox redeploy also starts everyone fresh. Synthetic timestamps follow 30-day fixture periods. This environment does not test durable crash recovery, real billing or live-provider delivery.
CommonQuant direct research routes
| Method and path | Response |
| GET /api-sandbox/market-hub/{symbol} | Actual TickerHubResponse schema: synthetic company, market structure, quote and option-expiry/ATM-IV summary. No real sources or raw live-chain/Greeks feed. |
| GET /api-sandbox/ticker-hub/{symbol} | The same CommonQuant direct hub schema, with dummy data. |
CommonQuant accountless B2B routes
Prefix /api-sandbox/business/wholesale/v1. Mutation request IDs and member IDs are nonzero UUIDs. Retry the same semantic input with the same request ID. Conflicting intent returns409; replay never returns a one-time license secret again. Every license serves one member; one member can own several separately selected licenses.
| Method and path | Input and contract |
| POST {prefix}/licenses | JSON requestId, externalUserId. BManagedResult with license, secretGeneration, secretAvailable, replayed; first issuance also includes licenseSecret. |
| GET {prefix}/licenses/{id} | Query externalUserId; current BManagedResult, no secret. |
| GET {prefix}/licenses/{id}/usage | Query externalUserId plus license secret. Mirrors the read-only usage shape: asOf, retailEntitlements, reports, usage, notifications. All amounts are dummy simulation values; reading them consumes nothing real. |
| POST {prefix}/licenses/{id}/reports/open | License secret; JSON requestId, externalUserId, kind: market, id: NVDA, policyVersion: wholesale-stored-research-2026-10-v1. Actual BStoredReport envelope with dummy stored sections, grant and receipt. Repeated opening counts once in the virtual report counter. |
| GET {prefix}/licenses/{id}/reports/market/{symbol} | Query externalUserId plus license secret. Requires a virtual report opening; returns BStoredReport, receipt:null, and explicit synthetic content/provenance. |
| POST {prefix}/licenses/{id}/revoke | JSON requestId, externalUserId. BManagedResult with revokedAt/detachedAt and revocationReason:revoked. Access denial is immediate and does not cancel, refund or charge anything. A replaced license returns 409 wholesale_assignment_replaced. |
| POST {prefix}/licenses/{id}/rotate-secret | JSON requestId, externalUserId. BManagedResult with a new licenseSecret and secretGeneration+1; the previous secret stops working immediately. Detached or revoked licenses return 403 wholesale_assignment_unavailable. |
| POST {prefix}/licenses/{id}/detach | JSON requestId, externalUserId. BManagedResult with detachedAt. Member access is denied at once and current report grants are cleared; counted reports stay counted. |
| POST {prefix}/licenses/{id}/reattach | JSON requestId, externalUserId. Requires a detached (or revoked, not replaced) license. Restores access and issues a new licenseSecret. Reports must be opened again; already counted ones are not counted twice. |
| POST {prefix}/licenses/{id}/replace | JSON requestId, externalUserId, newExternalUserId, reason (1-300 characters, no surrounding spaces or control characters). Requires a detached license. Returns the successor license (new id, replacesLicenseId, the new member) with its own licenseSecret; the predecessor becomes revocationReason:replaced and its counted reports carry over. Replay returns the successor without the secret. |
Cooldowns. Production requires 24 hours between detach and reattach or replace, and allows one genuine transfer per rolling 30 days (403 wholesale_detach_cooldown, wholesale_replacement_cooldown). The sandbox enforces the order of operations (403 wholesale_detach_required) but waives those waits so you can exercise the whole flow at once.
Business status and license views
Same X-CQ-Business-Key, production response shapes, synthetic values:
| Method and path | Production equivalent and response |
| GET /api-sandbox/business/status | GET /api/business/status. BPartnerStatus: readiness and the individual capacity tier (purchasedUnits, occupiedUnits, availableUnits). Capacity here is the 100-license fixture limit, counting revoked and replaced licenses; no price is stated. |
| GET /api-sandbox/business/licenses?after={id} | GET /api/business/licenses. BLicenses: this tenant's partner-managed licenses with status active, detached, revoked or replaced, 100 per page; follow nextCursor. |
| GET /api-sandbox/business/licenses/{id} | GET /api/business/licenses/{id}. BLicenseResult; unknown IDs return 404 license_not_found. |
Limits and unsupported operations
Only the reserved /api-sandbox namespace is supported on the API host. Production /api paths never enter live handlers here. At most 16 synthetic requests run concurrently with 12-second deadlines. The fixed examples require no production account, live credential, real balance or paid activation.
GET /api-sandbox/limits lists fixture-only caps:100 licenses,1,000 successful mutation receipts and1,000 shared hub/options/public-data fixture reads until you reset, 8 KiB bodies, 200 virtual reports per license. These are sandbox bounds, not live production allowance. Exhaustion simulates refusal without consuming actual units. Existing license allowances stay separate.
Wrong policy returns409 wholesale_policy_changed; missing report grant returns402 wholesale_report_access_required. Production-shaped errors use error.code. Sandbox-only expiration and fixture-capacity refusals remain explicit. Unknown endpoints never proxy to production. Not in the sandbox: buying paid capacity, owner sign-in and sessions, named (email) licenses and member claim, report quotes, embed sessions, notifications, live computation, billing and cancellation.
Commercial commitments and live entitlement values come from your approved agreement and authenticated production endpoints. This sandbox grants no production rights and does not define cancellation or refund terms.
Synthetic options integration
Use the same license, member UUID and sandbox-only license secret for GET /api-sandbox/business/wholesale/v1/licenses/{id}/options/chain/{symbol}. Its ListedChain body contains fixed synthetic quotes, IV and contracts, never provider data. An optional expiry must match the returned fixture expiry.
GET /api-sandbox/business/wholesale/v1/licenses/{id}/options/example/{symbol}?externalUserId={UUID} returns the exact supported comparison request. POST it unchanged to /api-sandbox/business/wholesale/v1/licenses/{id}/options/compare. Other market inputs return 422 sandbox_fixture_input_unsupported. This prevents the sandbox from becoming an unmetered real-data computation route.
The comparison shares production types and existing mathematical code: modelled delta, gamma, daily theta, vega per percentage point and exact scenario-weighted expiry P/L for two fixed synthetic strategies. Caller-declared scenario weights are not calibrated probabilities or an Oracle prediction. The body identifies synthetic_fixture. Neither options operation opens a real report, calls a provider, activates a paid license or spends any real allowance. They use only the finite fixture request cap, active tenant/member credentials and your test window.
Public data and analysis fixtures
The sandbox now includes GET /api-sandbox/instruments/search, /api-sandbox/market/stocks/{symbol}/price, /api-sandbox/market/stocks/{symbol}/ohlcv, /api-sandbox/market/symbols/{symbol}/ohlcv, /api-sandbox/market/batch-quote and /api-sandbox/market-hub/{symbol}/analytics. They use the actual CommonQuant response/query types and require the customer-isolated sandbox business key, without creating a paid license or account session.
Discovery simulates a small verified registry with AAPL, BTC and SPY, all named SYNTHETIC. Quotes explicitly identify commonquant_synthetic_fixture. History has eight fixed synthetic candles at supported timeframes; from/to/limit only filter those rows and never request provider history. Batch intraday/1y accepts the production-shaped query, at most50 symbols or5 for1y. Ready/current_delayed values describe the synthetic scenario, not market observations. Malformed typed query parameters can return400; decoded inputs outside this fixed subset return422.
Analytics uses the production DTO with explicit synthetic checks. Missing analytics/forecasts remain null; compatibility zeros are dummy placeholders, not real company scores. SPY is an ETF and BTC a crypto fixture, without fabricated company fundamentals. Public data, hubs and options share the same 1,000-read counter until you reset; another customer's counter is isolated. No real credit, report allowance, wallet, provider or refresh queue is touched. Unsupported account/Firebase/OAuth, wallet and paid-prediction routes never proxy to production.