Kinetic PRICING Developer docs Kinetic for developers

Kinetic Pricing API — v1

Pricing research for software businesses, exposed for authorized agents. This reference is generated from the live capability registry.

No account? POST /v1/signup-attempts starts agent-assisted signup (the account holder confirms by email). Have an account? Send the holder through OAuth consent, then call with the bearer token.

Static credential (e.g. Pilot secret store): the account holder creates an API access token in Integrations on the website, then your platform sends Authorization: Bearer kp_live_… to https://api.kineticpricing.com/v1. REST only — the MCP and OAuth surfaces reject static tokens. Rotate or revoke any time via kinetic.api_token_rotate / kinetic.api_token_revoke or the website.

accounts

GET /v1/account

Get the authorized account's profile.

operationId: accounts.get · method: kinetic.account_get · auth: scope: kinetic.account.read · risk: R0

Returns the account behind the current grant: id, email, and creation time. Mirrors what the account holder sees on the website.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

billing

POST /v1/billing/checkouts/pro

Start a Stripe checkout to subscribe to Kinetic Pro.

operationId: billing.createProCheckout · method: kinetic.pro_checkout_create · auth: scope: kinetic.billing.write · risk: R2

Creates (or reuses a still-open) Stripe subscription Checkout session for Kinetic Pro and returns `{checkout_url, interval, credit_applied_cents, expires_at?}` — the workspace owner completes payment on Stripe's hosted page in a browser. Card details never travel through this API: never collect or relay them. Over MCP the handoff arrives as a URL elicitation when your client supports it, otherwise as a structured body with `requires_user_action: true` and a `next_step`. `interval` is monthly or annual; `apply_credit` (default true) reserves any eligible one-use upgrade credit as an amount-off discount on the first invoice. Owner-only: non-owners get forbidden. If Pro is disabled it reads as resource_not_found; an already-active subscription or an in-flight payment fails with lifecycle_conflict; Stripe outages surface as external_dependency_failed. Requires an Idempotency-Key.

fieldinrequiredtype
intervalbodyyesstring
apply_creditbodynoboolean

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/billing/checkouts/study

Start a Stripe checkout to pay for a draft study.

operationId: billing.createStudyCheckout · method: kinetic.study_checkout_create · auth: scope: kinetic.billing.write · risk: R2

Creates (or reuses a still-open) Stripe Checkout session for a one-time study purchase and returns `{checkout_url, study_id, amount_cents, expires_at?}` — the account holder completes payment on Stripe's hosted page in a browser. Card details never travel through this API: never collect or relay them. Over MCP the handoff arrives as a URL elicitation when your client supports it, otherwise as a structured body with `requires_user_action: true` and a `next_step`. Preconditions: the study must belong to you and be in `draft` (a paid or non-draft study fails with lifecycle_conflict), and session-method studies must have a complete, valid configuration (otherwise validation_failed). The price is the server-owned amount stamped on the study; never trust client prices. On a Stripe outage the call fails with external_dependency_failed — retry shortly. Requires an Idempotency-Key.

fieldinrequiredtype
study_idbodyyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/billing/credits

Preview the one-use upgrade credit toward Kinetic Pro.

operationId: billing.getCredits · method: kinetic.credit_get · auth: scope: kinetic.billing.read · risk: R0

Computes the upgrade credit the account has earned from recent net one-time study purchases inside the trailing window: `eligible_cents`, the amount that would apply to a monthly (`applied_monthly_cents`) or annual (`applied_annual_cents`) plan, the `window_days`, the `source_study_count`, and a `reason` (`ok`, `no_recent_purchases`, or `already_redeemed`, since the credit is one-use-ever). Read-only; the credit is only actually reserved when you start a Pro checkout.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/billing/entitlements

Get the account's Kinetic Pro entitlement state.

operationId: billing.getEntitlements · method: kinetic.entitlement_get · auth: scope: kinetic.billing.read · risk: R0

Returns whether the authorized account (or, for a service account, the workspace owner it acts as) currently has Kinetic Pro: the entitlement `state`, whether it is `active`, whether the Workspace is `read_only` (had Pro, lost it), renewal/cancel and grace details, plus the pro/workspace/scenarios feature flags. Read-only.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/billing/offers

List purchasable offers: one-time study prices and Kinetic Pro plans.

operationId: billing.listOffers · method: kinetic.offer_list · auth: public · risk: R0

The complete, server-owned pricing surface. `study_methods` are the enabled one-time research methods with launch prices in integer cents and their methodology versions. `pro_subscription` is the Kinetic Pro subscription offer: monthly and annual prices in cents, the annual monthly-equivalent and annual savings, the seat limit, whether Pro/Workspace/scenarios are enabled, and whether checkout is currently available (with a reason when it is not). Public: no authentication required. Use these amounts before creating any checkout.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502.

GET /v1/billing/subscription

Get the account's Kinetic Pro subscription status.

operationId: billing.getSubscription · method: kinetic.subscription_get · auth: scope: kinetic.billing.read · risk: R0

Mirrors the website subscription panel: entitlement `state`, `active`, `read_only`, `cancel_at_period_end`, billing `interval`, `current_period_end`, `workspace_id`, and the acting user's `role`. Read-only. Use before cancel/resume to decide whether a change is needed.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/billing/subscription/cancel

Schedule the Kinetic Pro subscription to cancel at period end.

operationId: billing.cancelSubscription · method: kinetic.subscription_cancel · auth: scope: kinetic.billing.write · risk: R2

Turns on cancel-at-period-end: Kinetic Pro keeps running until the current period ends, then does not renew. Owner-only. Returns the resulting subscription status (same shape as get subscription). Idempotent: if cancellation is already scheduled, the current state is returned unchanged (not an error). With no active/canceling subscription it fails with resource_not_found. Repeat-safe; an Idempotency-Key is honored when provided.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/billing/subscription/resume

Undo a scheduled Kinetic Pro cancellation before it takes effect.

operationId: billing.resumeSubscription · method: kinetic.subscription_resume · auth: scope: kinetic.billing.write · risk: R2

Clears cancel-at-period-end so the subscription renews normally again. Owner-only. Returns the resulting subscription status (same shape as get subscription). Idempotent: if the subscription is not scheduled to cancel, the current state is returned unchanged (not an error). With no active subscription it fails with resource_not_found. Repeat-safe; an Idempotency-Key is honored when provided.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

help

GET /v1

Orient yourself: what Kinetic Pricing offers and how to proceed.

operationId: help.catalogue · method: kinetic.help · auth: public · risk: R0

Returns what this service does, how authentication works (OAuth consent for existing accounts, agent-assisted signup for new ones), and the full capability catalogue grouped by area with the scope each one needs. Call this first.

fieldinrequiredtype
areaquerynostring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502.

integrations

GET /v1/integrations/api-tokens

List the account's Kinetic API access tokens.

operationId: integrations.listApiTokens · method: kinetic.api_token_list · auth: scope: kinetic.integrations.read · risk: R0

Returns the acting user's static API access tokens: id, name, the public token prefix (kp_live_<public_id> — never the secret half), granted scopes, status (active/revoked/expired), and created/expires/last-used/rotated times. Secrets and secret hashes are never returned by any endpoint. Personal credentials: a service-account token is forbidden here.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/integrations/api-tokens

Create a Kinetic API access token (one-time secret).

operationId: integrations.createApiToken · method: kinetic.api_token_create · auth: scope: kinetic.integrations.write · risk: R3

Mints a static bearer token (kp_live_…) that delegates the acting user's live authority, restricted to the requested scopes. The full token is returned EXACTLY ONCE in `token` — store it immediately; it is never retrievable again. Scopes must be a subset of what the caller itself holds AND within the acting user's current workspace-role authority (viewers grant read scopes; editors add workspace writes; owners grant any scope); ["kinetic.full"] must be requested alone and only an account owner whose own credential carries kinetic.full may mint it. Optional expires_in_days (e.g. 30/90/365); a token minted by an expiring API token cannot outlive it. Tokens work only on the REST API host (api.kineticpricing.com) — the MCP, OAuth, and website surfaces reject them. Requires recent human authorization (10 minutes): an OAuth caller's grant must have been approved by the user within the window (re-run the authorization flow to refresh it — refreshing the access token does NOT count), and an API-token caller must itself carry a fresh authorization anchor (inherited from the human event that authorized its own mint). Stale callers receive `forbidden` with details.reason `recent_authorization_required`. Idempotency-Key is honored with HANDLER-MANAGED replay semantics: a replay returns the same token metadata with `token: null` (the secret is delivered exactly once, on the original response, and never enters any replay store).

fieldinrequiredtype
namebodyyesstring
scopesbodyyesarray
expires_in_daysbodynointeger

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

DELETE /v1/integrations/api-tokens/{id}

Revoke (disable) an API access token.

operationId: integrations.revokeApiToken · method: kinetic.api_token_revoke · auth: scope: kinetic.integrations.write · risk: R3

Disables the token so it can never authenticate again, effective immediately on the next request. Idempotent: revoking an already-revoked token still succeeds. A missing or foreign token reads as resource_not_found — list tokens first with kinetic.api_token_list to obtain a valid id.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/integrations/api-tokens/{id}/rotate

Rotate an API access token's secret (one-time secret).

operationId: integrations.rotateApiToken · method: kinetic.api_token_rotate · auth: scope: kinetic.integrations.write · risk: R3

Issues a brand-new token string (new public id and secret) for this token and invalidates the previous credential in the same atomic update — the old string stops working immediately. Name, scopes, and expiry are unchanged. The new token is returned EXACTLY ONCE in `token`. A missing, foreign, or revoked token reads as resource_not_found. Requires recent human authorization (10 minutes), same as token creation: OAuth callers need a freshly approved grant (refreshing the access token does NOT count) and API-token callers need a fresh authorization anchor; stale callers receive `forbidden` with details.reason `recent_authorization_required`. Idempotency-Key is honored with HANDLER-MANAGED replay semantics: a replay returns metadata with `token: null` — rotate again if the secret was lost.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/integrations/grants

List the account's OAuth grants (authorized clients).

operationId: integrations.listGrants · method: kinetic.grant_list · auth: scope: kinetic.integrations.read · risk: R0

Returns the active OAuth grants for the authorized account: which clients hold access, the client display name (from client metadata when available), the granted scopes, resource audiences, and created/updated/last-used times. Use a grant id with kinetic.grant_revoke to withdraw access.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

DELETE /v1/integrations/grants/{id}

Revoke an OAuth grant and its refresh tokens.

operationId: integrations.revokeGrant · method: kinetic.grant_revoke · auth: scope: kinetic.integrations.write · risk: R3

Withdraws a client's access: the grant is marked revoked and every refresh token derived from it is revoked immediately. Already-issued access tokens are short-lived and expire naturally rather than being invalidated here. Revoking an already-revoked grant succeeds idempotently. If the grant does not exist or belongs to another account you get resource_not_found — list grants first with kinetic.grant_list to obtain a valid id.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/integrations/service-accounts

List the workspace's service accounts.

operationId: integrations.listServiceAccounts · method: kinetic.service_account_list · auth: scope: kinetic.integrations.read · risk: R0

Returns the machine credentials (service accounts) belonging to the caller's Kinetic Workspace: id, name, client_id, granted scopes, status (active/revoked/expired), and created/last-used/rotated times. Secrets and secret hashes are never returned. Requires an active Kinetic Pro workspace.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/integrations/service-accounts

Create a workspace service account (client credentials).

operationId: integrations.createServiceAccount · method: kinetic.service_account_create · auth: scope: kinetic.integrations.write · risk: R3

Provisions a machine credential for the caller's Kinetic Workspace and returns a client_id and a one-time client_secret usable at the OAuth token endpoint (client_credentials grant). The secret is shown EXACTLY ONCE — store it immediately, it cannot be retrieved later. Scopes must be a subset of the account-holder scopes an owner can grant (kinetic.full is not accepted; list explicit scopes). Owner-only: only the workspace owner via a USER token may do this — a service-account token is forbidden (privilege escalation). Requires an active Kinetic Pro workspace.

fieldinrequiredtype
namebodyyesstring
scopesbodyyesarray

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

DELETE /v1/integrations/service-accounts/{id}

Revoke (disable) a service account.

operationId: integrations.revokeServiceAccount · method: kinetic.service_account_revoke · auth: scope: kinetic.integrations.write · risk: R3

Disables the service account so it can never authenticate again. Idempotent: revoking an already-revoked account still succeeds. Owner-only via a USER token; a service-account token is forbidden. If the account does not exist or belongs to another workspace you get resource_not_found. Requires an active Kinetic Pro workspace.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/integrations/service-accounts/{id}/rotate

Rotate a service account's secret.

operationId: integrations.rotateServiceAccount · method: kinetic.service_account_rotate · auth: scope: kinetic.integrations.write · risk: R3

Issues a new client_secret for the service account and immediately invalidates the previous one. The new secret is returned EXACTLY ONCE — store it now, it cannot be retrieved later. Owner-only via a USER token; a service-account token is forbidden. If the account does not exist, is revoked, or belongs to another workspace you get resource_not_found. Requires an active Kinetic Pro workspace.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

methods

GET /v1/methods

List available research methods with server-owned pricing.

operationId: methods.list · method: kinetic.method_list · auth: public · risk: R0

The catalogue of study methods (Van Westendorp, Gabor-Granger, MaxDiff, choice-based conjoint) that are currently enabled, with launch prices in cents, methodology versions, and sample-size guidance. Public: no authentication required.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502.

POST /v1/methods/recommendation

Recommend a research method for a pricing decision.

operationId: methods.recommend · method: kinetic.method_recommend · auth: public · risk: R0

Deterministic rules mapping the pricing decision you face to the best-fit method, with the reasoning and when to prefer an alternative. Decisions: price_range (what range will buyers accept), exact_price (which exact price to charge), feature_priorities (which features matter most), package_pricing (how to package features and price the bundle).

fieldinrequiredtype
decisionbodyyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502.

research

GET /v1/research

List the published research reports.

operationId: research.list · method: kinetic.research_list · auth: public · risk: R0

The public research library: every published report with its id, title, description, file size, and whether it is email-gated. Public — no authentication required. Use the id to fetch a single item or to download it.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502.

GET /v1/research/{slug}

Get one published research report by id.

operationId: research.get · method: kinetic.research_get · auth: public · risk: R0

Returns a single published research report's public metadata by its id (the library has no slug; the id is the identifier). Unpublished or unknown ids read as not found. Public — no authentication required.

fieldinrequiredtype
slugpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502.

POST /v1/research/{slug}/download

Download a published research report.

operationId: research.download · method: kinetic.research_download · auth: scope: kinetic.research.read · risk: R2

Authenticated equivalent of the website download: the calling account is treated as a verified lead (the download is stamped like a signed-in website download). For small reports (< 5 MB) the PDF is returned inline as { download: { content_type: 'application/pdf', encoding: 'base64', data } }. Larger reports return { download: null, download_url: null, note } because this surface has no signed-URL primitive and inlining megabytes of base64 is unreasonable — fetch those from the website research page. Unpublished or unknown ids read as not found; a missing storage object is an external_dependency_failed error.

fieldinrequiredtype
slugpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

results

GET /v1/studies/{id}/evidence

Get the structured decision evidence composed from a study's results.

operationId: results.getEvidence · method: kinetic.evidence_get · auth: scope: kinetic.results.read · risk: R0

Returns the evidence bundle the website results page composes from the current analysis snapshot and its statistics: the method core, per-segment slices, data-quality summary, sample guidance, confidence level, and documented limitations. Session-method studies (Van Westendorp vw-2, Gabor-Granger, MaxDiff, conjoint) only; legacy vw-1 studies return lifecycle_conflict pointing you to kinetic.results_get. Same response thresholds and not-found rules as kinetic.results_get.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/studies/{id}/exports/csv

Export a study's raw responses or computed results as CSV.

operationId: results.exportCsv · method: kinetic.results_export_csv · auth: scope: kinetic.results.export · risk: R2

Returns a CSV export inline as { kind, filename, content_type, csv }. Set "kind" to "responses" for the raw per-respondent response table, or "results" for the computed-results table (price points / curves / importances / utilities). The bytes match the website export exactly. Results exports need at least 5 valid responses or you get lifecycle_conflict with a fix hint. If the CSV exceeds ~2MB it is too large to return inline: csv is null and a note explains to download it from the website instead. Requires an Idempotency-Key. A missing or foreign study reads as resource_not_found.

fieldinrequiredtype
idpathyesstring
kindbodyyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/studies/{id}/narrative

Get the current written narrative for a study's results.

operationId: results.getNarrative · method: kinetic.narrative_get · auth: scope: kinetic.results.read · risk: R0

Returns the latest LLM-written markdown narrative for a study you own (narrative_md), with its version and generation time, or nulls when no narrative has been generated yet. To create or refresh one, call kinetic.narrative_generate. A missing or foreign study reads as resource_not_found.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/studies/{id}/narrative

Generate (or regenerate) the written narrative for a study's results.

operationId: results.generateNarrative · method: kinetic.narrative_generate · auth: scope: kinetic.studies.write · risk: R1

Computes the deterministic result, then asks the narrative model to write a fresh markdown report grounded strictly in those numbers, and appends it as a new report version. Preconditions: the study needs enough valid responses (same thresholds as kinetic.results_get) or you get lifecycle_conflict with a fix hint. If the model is unavailable or fails, you get external_dependency_failed (retryable) — retry shortly. A missing or foreign study reads as resource_not_found.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/studies/{id}/results

Get the deterministic analysis results for a study.

operationId: results.get · method: kinetic.results_get · auth: scope: kinetic.results.read · risk: R0

Returns the computed, snapshot-backed analysis for a study you own: price points, curves, importances, or utilities depending on the method, plus the confidence level, sample guidance, and valid-response count. Numbers come from the append-only analysis snapshot — the same figures the website results page shows. Preconditions: the study must have at least its method's developing-threshold of valid responses (15 for Van Westendorp/Gabor-Granger and legacy studies, 30 for MaxDiff, 50 for conjoint); if not, you get lifecycle_conflict with a fix hint telling you how many more responses to collect. A missing or foreign study reads as resource_not_found.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

signup

POST /v1/signup-attempts

Start agent-assisted signup for a new Kinetic Pricing account.

operationId: signup.start · method: kinetic.signup_start · auth: public · risk: R2

Creates a signup attempt and emails the account holder a confirmation link. Returns an attempt token (shown exactly once — store it). The account is only created after the holder clicks the link AND you call complete with terms_accepted=true. Never claim the account exists before completion succeeds. Enumeration-safe: the response never reveals whether the email already has an account.

fieldinrequiredtype
emailbodyyesstring
authority_basisbodyyesstring
client_idbodynostring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502.

GET /v1/signup-attempts/{id}

Check whether the account holder confirmed a signup attempt.

operationId: signup.status · method: kinetic.signup_status · auth: attempt token · risk: R0

Requires the attempt token from kinetic.signup_start (as the bearer on REST, or as attempt_token here). A wrong token reads as not found. States: pending_verification → verified → completed (or expired).

fieldinrequiredtype
idpathyesstring
attempt_tokenquerynostring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502.

POST /v1/signup-attempts/{id}/complete

Complete a verified signup attempt (explicit terms acceptance).

operationId: signup.complete · method: kinetic.signup_complete · auth: attempt token · risk: R2

Only works after the account holder clicked the emailed confirmation link (state=verified). You MUST pass terms_accepted=true — this records the account holder's acceptance of the terms version returned by kinetic.signup_start. Never call this without the holder's actual consent. Idempotent: repeating it returns the same completed state.

fieldinrequiredtype
idpathyesstring
terms_acceptedbodyyesboolean
attempt_tokenbodynostring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502.

studies

GET /v1/studies

List the account's studies.

operationId: studies.list · method: kinetic.study_list · auth: scope: kinetic.studies.read · risk: R0

Returns every study owned by the calling account, oldest first, each with its full setup, lifecycle status (draft/live/closed), pricing, public token, and archive state. Use this to find a study id before reading, editing, launching, or closing it.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/studies

Create a draft study.

operationId: studies.create · method: kinetic.study_create · auth: scope: kinetic.studies.write · risk: R1

Creates a new draft study. Pricing, methodology version, and the per-respondent design seed are server-owned and stamped at creation — never pass them. methodology defaults to van_westendorp; other methods must be enabled server-side (entitlement_required if not). After creating, generate its survey with kinetic.survey_regenerate, then launch with kinetic.study_launch. Requires an Idempotency-Key.

fieldinrequiredtype
namebodyyesstring
product_descbodyyesstring
segment_descbodyyesstring
decision_typebodyyesstring
currencybodyyesstring
current_pricesbodynoobject
category_tagbodynoobject
website_urlbodynoobject
gather_audience_infobodynoboolean
brand_voicebodynoobject
methodologybodynostring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/studies/{id}

Get one study by id.

operationId: studies.get · method: kinetic.study_get · auth: scope: kinetic.studies.read · risk: R0

Returns the full study by id, including its survey/method configuration and lifecycle status. Owner-only: a study that does not exist or belongs to another account reads as not_found (existence is never leaked).

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

PATCH /v1/studies/{id}

Edit a draft study.

operationId: studies.update · method: kinetic.study_update · auth: scope: kinetic.studies.write · risk: R1

Updates fields on a DRAFT study; only provided fields change. Draft-only: editing a live/closed study fails with lifecycle_conflict (details.fix suggests duplicating it). method_config is accepted only for session-method studies and is validated server-side (validation_failed with per-field errors otherwise).

fieldinrequiredtype
idpathyesstring
namebodynoobject
product_descbodynoobject
segment_descbodynoobject
decision_typebodynoobject
currencybodynoobject
current_pricesbodynoobject
category_tagbodynoobject
website_urlbodynoobject
gather_audience_infobodynoobject
brand_voicebodynoobject
survey_configbodynoobject
method_configbodynoobject

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

DELETE /v1/studies/{id}

Permanently delete an empty draft study.

operationId: studies.delete · method: kinetic.study_delete · auth: scope: kinetic.studies.delete · risk: R3

Permanently deletes a study, reserved for accidental duplicates and abandoned test drafts. ONLY empty, unpaid, never-activated drafts with zero response/analysis history qualify; everything else must be archived (lifecycle_conflict, details.fix points at kinetic.study_archive). You must pass confirm_name matching the study's exact name. Any open Stripe checkout is expired first, and all checks run under a FOR UPDATE row lock, so no payment can complete after deletion. If Stripe cannot be reached, nothing is deleted (external_dependency_failed). Honors an Idempotency-Key when supplied.

fieldinrequiredtype
idpathyesstring
confirm_namequeryyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/studies/{id}/archive

Archive a study (soft hide).

operationId: studies.archive · method: kinetic.study_archive · auth: scope: kinetic.studies.lifecycle · risk: R1

Archives a study of any status: it is hidden from the main dashboard list while responses, analysis, and payment history are left untouched. Idempotent — archiving an already-archived study succeeds and keeps the original archive timestamp. Reverse with kinetic.study_restore. Honors an Idempotency-Key when supplied.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/studies/{id}/close

Close a live study.

operationId: studies.close · method: kinetic.study_close · auth: scope: kinetic.studies.lifecycle · risk: R3

Closes a LIVE study: the respondent link then tells visitors the study has ended, while results stay available. Idempotent — closing an already-closed study succeeds and returns it unchanged. Closing a draft (never launched) fails with lifecycle_conflict. Honors an Idempotency-Key when supplied.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/studies/{id}/duplicate

Duplicate a study into a fresh draft.

operationId: studies.duplicate · method: kinetic.study_duplicate · auth: scope: kinetic.studies.write · risk: R1

Copies a study's setup (context, survey/method configuration) into a new draft named '<name> (Copy)'. Publish state (public token, payment, close/archive timestamps) intentionally starts clean; the copy gets its own respondent design seed. Requires an Idempotency-Key.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/studies/{id}/launch

Launch a draft study under Kinetic Pro.

operationId: studies.launch · method: kinetic.study_launch · auth: scope: kinetic.studies.launch · risk: R2

Publishes a DRAFT study live under the account owner's Kinetic Pro subscription (no per-study payment) and mints its public respondent link. Requires an active Pro subscription owned by the caller — otherwise payment_required with details.fix pointing at kinetic.pro_checkout_create. Draft-only and readiness-gated (incomplete configs fail validation). Already-paid or non-draft studies fail with lifecycle_conflict. Requires an Idempotency-Key.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/studies/{id}/preview

Preview a study's respondent survey payload.

operationId: studies.previewSurvey · method: kinetic.survey_preview · auth: scope: kinetic.studies.read · risk: R0

Returns the exact payload a respondent would receive for a session-method study, owner-only, so you can review the survey before launch. Read-only and stores nothing. Studies whose config is incomplete return validation_failed.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/studies/{id}/preview/complete

Validate a preview submission without storing it.

operationId: studies.previewCheck · method: kinetic.survey_preview_check · auth: scope: kinetic.studies.read · risk: R0

Validates a preview session's answers and segmentation with exactly the same rules as a real respondent completion, then stores NOTHING. Use it to confirm the survey accepts a plausible submission. respondent_key must come from kinetic.survey_preview_start; duration_ms is the elapsed answer time in milliseconds.

fieldinrequiredtype
idpathyesstring
respondent_keybodyyesstring
answersbodynoobject
segmentationbodynoobject
duration_msbodyyesinteger

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/studies/{id}/preview/session

Start an ephemeral preview session for a study.

operationId: studies.previewStart · method: kinetic.survey_preview_start · auth: scope: kinetic.studies.read · risk: R0

Assigns a respondent design exactly as the live flow would and returns a preview session (respondent_key + design). EPHEMERAL: nothing is written to the database, so preview activity never appears in counts, analysis, or exports. Pass the returned respondent_key back to kinetic.survey_preview_check.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/studies/{id}/progress

Get live response progress and confidence for a study.

operationId: studies.getProgress · method: kinetic.study_progress_get · auth: scope: kinetic.studies.read · risk: R0

Returns response counts (started, completed, valid, flagged), completion rate, a confidence level (insufficient/directional/cautious/full), sample-size guidance, and — once enough valid responses exist — a deterministic live analysis result. Reflects data as it arrives while the study is live.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/studies/{id}/quality

Get response quality (flag) aggregates for a study.

operationId: studies.getQuality · method: kinetic.study_quality_get · auth: scope: kinetic.studies.read · risk: R0

Returns the quality-flag aggregates for a study: completed vs. valid counts, the flagged count, and the flag rate. These are the same flag figures surfaced inside the study's progress; use them to judge whether responses are trustworthy.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/studies/{id}/respondent-link

Get a study's public respondent link.

operationId: studies.getRespondentLink · method: kinetic.respondent_link_get · auth: scope: kinetic.studies.read · risk: R0

Returns the public respondent URL and token for a launched study — the same link the dashboard shares (/s/<public_token>). A study that has not been launched yet has no link (lifecycle_conflict, details.fix points at kinetic.study_launch).

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/studies/{id}/restore

Restore an archived study.

operationId: studies.restore · method: kinetic.study_restore · auth: scope: kinetic.studies.lifecycle · risk: R1

Un-archives a study, returning it to the main dashboard list. Idempotent — restoring a study that is not archived succeeds and returns it unchanged. Honors an Idempotency-Key when supplied.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/studies/{id}/survey/regenerate

Generate (or regenerate) a study's survey with AI.

operationId: studies.regenerateSurvey · method: kinetic.survey_regenerate · auth: scope: kinetic.studies.write · risk: R1

Uses the model to produce a survey for the study from its context (product, segment, decision, currency, brand voice) and saves it as the study's survey config, replacing any prior one. Owner-only. The model being unavailable is external_dependency_failed — retry shortly.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/studies/prefill

Suggest study context by reading a founder's website with AI.

operationId: studies.prefillFromWebsite · method: kinetic.study_prefill · auth: scope: kinetic.studies.write · risk: R2

Fetches the given website and uses the model to extract suggested study-setup fields (name, product/segment descriptions, visible pricing, currency, brand voice). Stores nothing — feed the suggestions into kinetic.study_create. A site that cannot be read is validation_failed on url; the model being unavailable is external_dependency_failed (fill the fields manually instead).

fieldinrequiredtype
urlbodyyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

tasks

GET /v1/tasks/{id}

Poll a long-running task you started.

operationId: tasks.get · method: kinetic.task_get · auth: authenticated (any bearer) · risk: R0

Returns the task envelope (state: queued|running|input_required|succeeded|failed|cancelled, progress, result, error) for a task created by one of your earlier calls. Tasks are only visible to the credential that created them; anything else reads as not found. Task records expire after about 7 days and are purged on expiry. On MCP this surface also answers the tasks/get JSON-RPC method with the wire vocabulary (working|input_required|completed|failed|cancelled).

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/tasks/{id}/cancel

Cancel a task that has not finished.

operationId: tasks.cancel · method: kinetic.task_cancel · auth: authenticated (any bearer) · risk: R1

Cancels a task in state queued or input_required. Tasks execute inline on this deployment, so a task observed in state running is actively executing inside its creating request and cannot be aborted (lifecycle_conflict) — poll until it settles. Terminal tasks (succeeded, failed, cancelled) also answer lifecycle_conflict. Only the credential that created the task can cancel it. On MCP this surface also answers the tasks/cancel JSON-RPC method.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/tasks/{id}/input

Supply the input a paused task is waiting on.

operationId: tasks.update · method: kinetic.task_update · auth: authenticated (any bearer) · risk: R1

Continues a task in state input_required by supplying the requested input; execution resumes inline and the returned envelope is the settled task (succeeded or failed). Tasks in any other state answer lifecycle_conflict. Only the credential that created the task can update it. On MCP this surface also answers the tasks/update JSON-RPC method.

fieldinrequiredtype
idpathyesstring
inputbodyyesobject

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

team

GET /v1/team

List the workspace's team members and seat usage.

operationId: team.get · method: kinetic.team_get · auth: scope: kinetic.team.read · risk: R0

Returns every non-revoked seat in the caller's Kinetic Pro workspace (owner included): id, email of accepted members, role, status, and invited/joined timestamps, plus seat_limit and seats_used. Requires an active Pro subscription. Read-only.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/team/invitations

List outstanding team invitations.

operationId: team.listInvitations · method: kinetic.invitation_list · auth: scope: kinetic.team.read · risk: R0

Returns the pending 'invited' seats for the workspace, each with its expiry (invite_expires_at). Use kinetic.member_invite to create one and kinetic.invitation_accept to accept. Read-only.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/team/invitations

Invite a collaborator to the workspace.

operationId: team.invite · method: kinetic.member_invite · auth: scope: kinetic.team.write · risk: R2

Owner-only. Sends an email invitation for an editor or viewer seat. Kinetic Pro includes 3 seats total (owner included, counting outstanding invites); a full workspace returns lifecycle_conflict — remove a member first. Re-inviting a pending address refreshes that invitation. An address that already has a seat returns lifecycle_conflict. Requires an Idempotency-Key.

fieldinrequiredtype
emailbodyyesstring
rolebodyyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/team/invitations/{token}/accept

Accept a team invitation using its emailed token.

operationId: team.acceptInvitation · method: kinetic.invitation_accept · auth: invite token · risk: R2

The authenticated user accepts an invitation with the token from the invite email. Only a user token can accept (service accounts are forbidden). The caller's email must match the invited address; a wrong, expired, or already-used token returns resource_not_found. Safe to retry (replay).

fieldinrequiredtype
tokenpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

PATCH /v1/team/members/{id}

Change a team member's role.

operationId: team.updateRole · method: kinetic.member_role_update · auth: scope: kinetic.team.write · risk: R3

Owner-only. Sets a member's role to editor or viewer. The owner row cannot be re-roled (lifecycle_conflict). A member id outside this workspace returns resource_not_found.

fieldinrequiredtype
idpathyesstring
rolebodyyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

DELETE /v1/team/members/{id}

Remove a team member from the workspace.

operationId: team.removeMember · method: kinetic.member_remove · auth: scope: kinetic.team.write · risk: R3

Owner-only. Revokes a seat, freeing it for a new invite. The owner seat cannot be removed (lifecycle_conflict). Removing an already-revoked member is an idempotent success returning the current state. Safe to retry (replay).

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

teardowns

POST /v1/teardowns

Run a pricing-page teardown for a URL.

operationId: teardowns.create · method: kinetic.teardown_create · auth: scope: kinetic.teardown.write · risk: R2

Creates a teardown for the given pricing page URL and scores it synchronously in the same call: it fetches the page (plain HTTP, then a headless render fallback) and analyzes clarity, structure, and persuasion across the rubric dimensions. The teardown is owned by the calling account and its full report is returned unlocked. If the page cannot be read automatically (bot-blocked, login-walled, or too thin), the teardown comes back in status 'error' with details.state='needs_manual_text' — do NOT treat this as a hard failure: follow details.fix and call kinetic.teardown_manual_text with the pasted pricing text. The model provider being unavailable is an external_dependency_failed error.

fieldinrequiredtype
urlbodyyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/teardowns/{id}

Get a pricing teardown and its full report.

operationId: teardowns.get · method: kinetic.teardown_get · auth: scope: kinetic.teardown.write · risk: R0

Returns the teardown by id with its full report (the agent surface is authenticated and reports are always unlocked for their owner). Owner-only: a teardown belonging to another account reads as not found. A teardown stuck in pending/processing past the stale threshold is flipped to error automatically before it is returned.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/teardowns/{id}/manual-text

Score a teardown from pasted pricing page text.

operationId: teardowns.manualText · method: kinetic.teardown_manual_text · auth: scope: kinetic.teardown.write · risk: R1

Rescue path for a teardown that could not be read automatically (status 'error' with details.state='needs_manual_text'). Paste at least 200 characters of the pricing page's text; it replaces the failed fetch and is scored with the same analysis as an automatic run. Owner-only. If the teardown is not in an error state, its current state is returned unchanged.

fieldinrequiredtype
idpathyesstring
textbodyyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/teardowns/{id}/unlock

Ensure a teardown's full report is unlocked.

operationId: teardowns.unlock · method: kinetic.teardown_unlock · auth: scope: kinetic.teardown.write · risk: R2

Account-owned teardowns are already unlocked for their owner on this surface, so this is an idempotent no-op: it confirms ownership and returns the full report. No email is sent (the website's email-unlock gate applies only to legacy, account-less teardowns). A teardown owned by another account reads as not found.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

webhooksOut

GET /v1/integrations/webhook-deliveries

List outbound webhook delivery attempts.

operationId: webhooksOut.listDeliveries · method: kinetic.webhook_delivery_list · auth: scope: kinetic.integrations.read · risk: R0

Returns delivery records for your endpoints (newest first): state (pending/succeeded/failed/exhausted), attempt count, last HTTP status, a redacted response snippet, next scheduled attempt, and retried_from_delivery_id when the row is a manual retry. Optionally filter by endpoint_id and/or state; page size is bounded (default 25, max 100). Use kinetic.webhook_delivery_retry to re-attempt a failed or exhausted delivery.

fieldinrequiredtype
endpoint_idquerynostring
statequerynostring
limitquerynointeger

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/integrations/webhook-deliveries/{id}/retry

Retry a failed or exhausted webhook delivery.

operationId: webhooksOut.retryDelivery · method: kinetic.webhook_delivery_retry · auth: scope: kinetic.integrations.write · risk: R2

Enqueues a NEW pending delivery for the same endpoint and event as the given delivery, with retried_from_delivery_id pointing back at it. Only failed or exhausted deliveries can be retried (a pending one returns lifecycle_conflict). Replay-idempotent: retrying a delivery that has already been retried returns the existing retry instead of creating another. Idempotency-Key is honored when present.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/integrations/webhooks

List your outbound webhook endpoints.

operationId: webhooksOut.list · method: kinetic.webhook_list · auth: scope: kinetic.integrations.read · risk: R0

Returns the caller's webhook subscriber endpoints (newest first): id, destination url, subscribed event types, enabled flag, and each endpoint's ETag. Signing secrets are never returned — they are shown only once at creation. Use kinetic.webhook_create to add one, kinetic.webhook_update to change or disable one.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/integrations/webhooks

Create an outbound webhook endpoint.

operationId: webhooksOut.create · method: kinetic.webhook_create · auth: scope: kinetic.integrations.write · risk: R2

Registers an https endpoint that receives signed JSON POSTs for the event types you subscribe to (use "*" for all). The response includes the signing `secret` (whsec_...) EXACTLY ONCE — store it now; it can never be retrieved again. Each delivery carries X-Kinetic-Signature: t=<unix_ts>,v1=<hex hmac-sha256 of "<t>.<raw body>" keyed by the secret>, plus X-Kinetic-Event, X-Kinetic-Delivery, and User-Agent Kinetic-Webhooks/1. Receivers must recompute the HMAC and reject deliveries whose t is outside a 5-minute tolerance window. URLs must be https (http allowed only for localhost outside production); private/loopback/link-local/metadata hosts are rejected. Requires an Idempotency-Key. Fails with external_dependency_failed if webhook signing is not configured on this deployment.

fieldinrequiredtype
urlbodyyesstring
eventsbodyyesarray
descriptionbodynostring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

PATCH /v1/integrations/webhooks/{id}

Update an outbound webhook endpoint.

operationId: webhooksOut.update · method: kinetic.webhook_update · auth: scope: kinetic.integrations.write · risk: R2

Changes an endpoint's destination url, subscribed event types, description, or enabled flag (active). The signing secret is never affected and cannot be revealed or rotated here. Send If-Match with the endpoint's current ETag for optimistic concurrency; on a 412 version_conflict, re-read with kinetic.webhook_list and retry. Disable an endpoint by setting active=false rather than deleting it if you want to keep its delivery history.

fieldinrequiredtype
idpathyesstring
urlbodynostring
eventsbodynoarray
descriptionbodynoobject
activebodynoboolean

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401/412.

DELETE /v1/integrations/webhooks/{id}

Delete an outbound webhook endpoint.

operationId: webhooksOut.delete · method: kinetic.webhook_delete · auth: scope: kinetic.integrations.write · risk: R3

Removes an endpoint so it stops receiving events; any still-pending deliveries are cancelled. A repeat delete or a delete of an endpoint you do not own reads as resource_not_found. Idempotency-Key is honored when present (replay-safe).

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

workspace

GET /v1/workspace

Get the Kinetic Workspace with role, entitlement, and counts.

operationId: workspace.get · method: kinetic.workspace_get · auth: scope: kinetic.workspace.read · risk: R0

Returns the caller's workspace profile, their role (owner/editor/viewer), the owner's Kinetic Pro entitlement summary, activity counts (scenarios, decisions, studies, active members), and the latest plan and metric snapshots. Requires an active or read-only Pro history; otherwise fails entitlement_required with a checkout hint. Returns an ETag you can pass as If-Match to kinetic.workspace_update.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

PATCH /v1/workspace

Update the Kinetic Workspace profile.

operationId: workspace.update · method: kinetic.workspace_update · auth: scope: kinetic.workspace.write · risk: R1

Patches workspace profile fields the owner controls: name, company_name, product_names, business_model, value_metric, currency (3-letter code), report_brand_name, and complete_onboarding (set true once to fire the one-time onboarding conversion). Requires a writing role and active Pro. Send If-Match with the ETag from kinetic.workspace_get for optimistic concurrency; on version_conflict re-read and retry. Returns the refreshed bundle and a new ETag.

fieldinrequiredtype
namebodynostring
company_namebodynoobject
product_namesbodynoarray
business_modelbodynoobject
value_metricbodynoobject
currencybodynostring
report_brand_namebodynoobject
complete_onboardingbodynoboolean

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401/412.

GET /v1/workspace/cohorts

List this workspace's cohorts with their tagged share links.

operationId: workspace.listCohorts · method: kinetic.cohort_list · auth: scope: kinetic.workspace.read · risk: R0

Cohorts group tagged respondent share links across studies so you can compare audiences. Returns the newest 100 cohorts (each with its links). Requires an active Kinetic Pro workspace; if you get entitlement_required, complete a Pro checkout first.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/workspace/cohorts

Create a cohort to group tagged share links.

operationId: workspace.createCohort · method: kinetic.cohort_create · auth: scope: kinetic.workspace.write · risk: R1

Creates a named cohort in the caller's workspace. Add tagged study share links to it with kinetic.cohort_link_create. Requires a writable Kinetic Pro workspace seat. Send an Idempotency-Key to make retries safe.

fieldinrequiredtype
namebodyyesstring
descriptionbodynoobject

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/workspace/cohorts/{cohortId}/archive

Archive a cohort (links stop resolving; history kept).

operationId: workspace.archiveCohort · method: kinetic.cohort_archive · auth: scope: kinetic.workspace.write · risk: R1

Archives a cohort so its links stop resolving while history is preserved. Idempotent: re-archiving an already-archived cohort simply refreshes its archived-at timestamp and succeeds. Returns resource_not_found if the cohort is not in this workspace. Requires a writable Pro seat.

fieldinrequiredtype
cohortIdpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/workspace/cohorts/{cohortId}/links

Mint a tagged share link for a study under a cohort.

operationId: workspace.createCohortLink · method: kinetic.cohort_link_create · auth: scope: kinetic.workspace.write · risk: R1

Adds a study share link (with an optional label) to a cohort. The study must belong to the workspace owner. Fails with lifecycle_conflict if the cohort is archived, or resource_not_found if the cohort or study is not in this workspace. Requires a writable Pro seat; send an Idempotency-Key.

fieldinrequiredtype
cohortIdpathyesstring
studyIdbodyyesstring
labelbodynoobject

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/workspace/decisions

List decision records visible to the caller.

operationId: workspace.listDecisions · method: kinetic.decision_list · auth: scope: kinetic.workspace.read · risk: R0

Decision records capture what you decided from a study or scenario. NOT gated on Kinetic Pro: any study purchaser sees their own personal decisions. When the caller has a workspace, its shared decisions are included too. Returns the newest 200.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/workspace/decisions

Record a pricing decision (works without Pro for study owners).

operationId: workspace.createDecision · method: kinetic.decision_create · auth: scope: kinetic.workspace.write · risk: R1

Records a decision linked to a study OR a scenario (at least one required). Study links require you to own the study. Scenario links require an active Kinetic Pro workspace seat (else entitlement_required); when a scenarioRunId is given, the modeled projection is frozen from that immutable run. If you have a writable workspace the decision attaches to it, otherwise it is personal. Send an Idempotency-Key.

fieldinrequiredtype
titlebodyyesstring
actionTypebodyyesstring
decisionbodyyesobject
reasonbodynoobject
studyIdbodynoobject
scenarioIdbodynoobject
scenarioRunIdbodynoobject
calcRecommendationbodynoobject
effectiveDatebodynoobject
reviewAtbodynoobject

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/workspace/decisions/{decisionId}

Get one decision with its outcome check-ins.

operationId: workspace.getDecision · method: kinetic.decision_get · auth: scope: kinetic.workspace.read · risk: R0

Returns a decision (frozen calc recommendation / modeled projection included) plus its outcome check-ins, newest first. Visible to the decision's creator, owner, or workspace members. Returns resource_not_found otherwise. The response carries an ETag; pass it as If-Match when updating.

fieldinrequiredtype
decisionIdpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

PATCH /v1/workspace/decisions/{decisionId}

Update owner-decision fields or status (frozen copies never change).

operationId: workspace.updateDecision · method: kinetic.decision_update · auth: scope: kinetic.workspace.write · risk: R1

Patches a decision's title, decision body, reason, status, effective date, or review date. Frozen copies (calc recommendation, modeled projection) can never change. Requires edit rights (creator/owner, or a writable workspace seat) else forbidden. Supports If-Match: pass the ETag from kinetic.decision_get to avoid clobbering concurrent edits.

fieldinrequiredtype
decisionIdpathyesstring
titlebodynostring
decisionbodynoobject
reasonbodynoobject
effectiveDatebodynoobject
reviewAtbodynoobject
statusbodynostring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401/412.

POST /v1/workspace/decisions/{decisionId}/outcomes

Add an observational outcome check-in to a decision.

operationId: workspace.createOutcome · method: kinetic.outcome_create · auth: scope: kinetic.workspace.write · risk: R1

Appends an append-only outcome check-in (observedAt + an aggregates-only, non-empty metrics object + optional note) to a decision. If the decision was review_due, recording an outcome moves it to reviewed. Requires edit rights (else forbidden). Send an Idempotency-Key.

fieldinrequiredtype
decisionIdpathyesstring
observedAtbodyyesstring
metricsbodyyesobject
notebodynoobject

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/workspace/evidence-links

Link a study claim to a scenario assumption.

operationId: workspace.linkEvidence · method: kinetic.evidence_link · auth: scope: kinetic.workspace.write · risk: R1

Attaches an evidence link binding a claim from one of the workspace owner's studies (via an immutable analysis snapshot of THAT study) to a scenario assumption. scenario_id, study_id, snapshot_id, and claim (with a string claim.assumptionKey) are required; optional cohort_id must belong to this workspace. Cross-tenant study/snapshot ids read as resource_not_found. Requires a writing role, active Pro, and an Idempotency-Key.

fieldinrequiredtype
scenario_idbodyyesstring
study_idbodyyesstring
snapshot_idbodyyesstring
claimbodyyesobject
cohort_idbodynoobject

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

DELETE /v1/workspace/evidence-links/{id}

Delete a scenario evidence link.

operationId: workspace.unlinkEvidence · method: kinetic.evidence_unlink · auth: scope: kinetic.workspace.write · risk: R1

Removes an evidence link by id within the caller's workspace and returns { deleted: true }. Unknown or cross-tenant ids read as resource_not_found. Safe to repeat with the same Idempotency-Key. Requires a writing role and active Pro.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/workspace/metric-snapshots

List metric snapshots, newest month/version first.

operationId: workspace.listMetricSnapshots · method: kinetic.metric_snapshot_list · auth: scope: kinetic.workspace.read · risk: R0

Returns up to 60 append-only metric snapshots for the workspace, newest effective_month and version first. Each snapshot pins the workspace's monthly business metrics (integer cents / basis points). Create new versions with kinetic.metric_snapshot_create.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/workspace/metric-snapshots

Append a metric snapshot for a month.

operationId: workspace.createMetricSnapshot · method: kinetic.metric_snapshot_create · auth: scope: kinetic.workspace.write · risk: R1

Appends an immutable metric snapshot (source=owner) for a month, with the next version for that month allocated under a row lock. effective_month must be the first day of a month (YYYY-MM-01). metrics must be a non-empty object; every number anywhere must be a safe integer (cents / basis points), else validation_failed names the offending path. Requires a writing role, active Pro, and an Idempotency-Key.

fieldinrequiredtype
effective_monthbodyyesstring
metricsbodyyesobject
notebodynostring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/workspace/plan-snapshots

List plan snapshots, newest version first.

operationId: workspace.listPlanSnapshots · method: kinetic.plan_snapshot_list · auth: scope: kinetic.workspace.read · risk: R0

Returns up to 50 append-only plan snapshots for the workspace, newest version first. Each snapshot pins a versioned set of plans (integer cents / basis points) effective at a point in time. Create new versions with kinetic.plan_snapshot_create.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/workspace/plan-snapshots

Append a new plan snapshot version.

operationId: workspace.createPlanSnapshot · method: kinetic.plan_snapshot_create · auth: scope: kinetic.workspace.write · risk: R1

Appends an immutable plan snapshot (source=owner) with the next version allocated under a row lock. plans must be a non-empty array of objects, each with a non-empty name; every number anywhere in the payload must be a safe integer (cents / basis points), else validation_failed names the offending path. effective_at is an ISO date-time. Requires a writing role, active Pro, and an Idempotency-Key.

fieldinrequiredtype
plansbodyyesarray
effective_atbodyyesstring
notebodynostring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/workspace/reminders

List the caller's workspace reminders.

operationId: workspace.listReminders · method: kinetic.reminder_list · auth: scope: kinetic.workspace.read · risk: R0

Reminders are owner-chosen (never automatic) nudges for a scenario review, a series wave, or a decision review. Returns the caller's newest 100 reminders in this workspace, by due date. Requires an active Kinetic Pro workspace.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/workspace/reminders

Create an owner-chosen reminder (never automatic).

operationId: workspace.createReminder · method: kinetic.reminder_create · auth: scope: kinetic.workspace.write · risk: R1

Schedules a reminder of kind scenario_review, series_wave, or decision_review, due in the future, targeting a record that lives in this workspace (else resource_not_found). Duplicate (same kind + target + due time) → lifecycle_conflict. Requires a writable Pro seat; send an Idempotency-Key.

fieldinrequiredtype
kindbodyyesstring
targetIdbodyyesstring
dueAtbodyyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/workspace/reminders/{reminderId}/cancel

Cancel a pending reminder.

operationId: workspace.cancelReminder · method: kinetic.reminder_cancel · auth: scope: kinetic.workspace.write · risk: R1

Cancels one of the caller's pending reminders (not yet sent, not already canceled). Idempotency mode replay: an Idempotency-Key is optional but honored. Returns resource_not_found if the reminder is missing, already sent, or already canceled. Requires an active Kinetic Pro workspace.

fieldinrequiredtype
reminderIdpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/workspace/scenarios

List revenue scenarios with their latest run summary.

operationId: workspace.listScenarios · method: kinetic.scenario_list · auth: scope: kinetic.workspace.read · risk: R0

Returns up to 100 scenarios for the workspace, newest updated first, each with its latest run summary. Archived scenarios are excluded unless include_archived=true. Fails resource_not_found when revenue scenarios are disabled for this deployment.

fieldinrequiredtype
include_archivedquerynoboolean

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/workspace/scenarios

Create a revenue scenario container.

operationId: workspace.createScenario · method: kinetic.scenario_create · auth: scope: kinetic.workspace.write · risk: R1

Creates an empty scenario (status=draft) with a required name and an optional 3-letter currency (defaults to the workspace currency). Run it with kinetic.scenario_run to append the first version. Requires a writing role, active Pro, and an Idempotency-Key.

fieldinrequiredtype
namebodyyesstring
currencybodynostring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/workspace/scenarios/{id}

Get a scenario with its runs and evidence links.

operationId: workspace.getScenario · method: kinetic.scenario_get · auth: scope: kinetic.workspace.read · risk: R0

Returns one scenario (with its latest run), up to 25 recent runs, and all evidence links. Unknown or cross-tenant ids read as resource_not_found. Returns an ETag you can pass as If-Match to kinetic.scenario_update.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

PATCH /v1/workspace/scenarios/{id}

Rename, restatus, or archive/unarchive a scenario.

operationId: workspace.updateScenario · method: kinetic.scenario_update · auth: scope: kinetic.workspace.write · risk: R1

Patches a scenario's name, status (draft|ready|approved|launched|review_due|reviewed|reversed), or archived flag (true archives, false unarchives). Unknown or cross-tenant ids read as resource_not_found. Send If-Match with the ETag from kinetic.scenario_get; on version_conflict re-read and retry. Requires a writing role and active Pro.

fieldinrequiredtype
idpathyesstring
namebodynostring
statusbodynostring
archivedbodynoboolean

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401/412.

POST /v1/workspace/scenarios/{id}/archive

Archive a scenario (idempotent).

operationId: workspace.archiveScenario · method: kinetic.scenario_archive · auth: scope: kinetic.workspace.write · risk: R1

Archives a scenario by setting its archived_at timestamp if not already archived; archived scenarios are excluded from kinetic.scenario_list unless include_archived=true. Idempotent: re-archiving an already-archived scenario returns the same object. Unknown or cross-tenant ids read as resource_not_found. Unarchive via kinetic.scenario_update with archived=false. Requires a writing role and active Pro.

fieldinrequiredtype
idpathyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/workspace/scenarios/{id}/runs

Run the deterministic engine and append an immutable run.

operationId: workspace.runScenario · method: kinetic.scenario_run · auth: scope: kinetic.workspace.write · risk: R1

Executes the revenue-scenario engine on your full ScenarioInput (integer cents / basis points; validated server-side) and appends an immutable run with the next version and the pinned engine_version. Optional plan_snapshot_id / metric_snapshot_id must belong to this workspace; when omitted the latest of each is pinned automatically. Archived scenarios fail lifecycle_conflict (unarchive first). Bad engine inputs fail validation_failed with the offending field. Requires a writing role, active Pro, and an Idempotency-Key.

fieldinrequiredtype
idpathyesstring
labelbodynostring
inputsbodyyesobject
plan_snapshot_idbodynoobject
metric_snapshot_idbodynoobject

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/workspace/series

List study series with their waves.

operationId: workspace.listSeries · method: kinetic.series_list · auth: scope: kinetic.workspace.read · risk: R0

A study series tracks the same pricing question over time — each wave is a study using one shared method. Returns the newest 100 series, each with its ordered waves (wave number, study id, name, and status). Requires an active Kinetic Pro workspace.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/workspace/series

Create a study series (one question, one method).

operationId: workspace.createSeries · method: kinetic.series_create · auth: scope: kinetic.workspace.write · risk: R1

Creates a series pinned to a single research method. Optionally seed it with firstStudyId as wave 1 — that study must belong to the workspace owner and use the same method (else lifecycle_conflict). Requires a writable Pro seat; send an Idempotency-Key.

fieldinrequiredtype
namebodyyesstring
questionbodynoobject
methodbodyyesstring
reviewCadencebodynoobject
firstStudyIdbodynoobject

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

POST /v1/workspace/series/{seriesId}/waves

Attach a study as the next wave in a series.

operationId: workspace.addSeriesWave · method: kinetic.series_wave_add · auth: scope: kinetic.workspace.write · risk: R1

Appends a study as the next wave. The study must belong to the workspace owner and use the SAME method as the series (else lifecycle_conflict). A study can appear at most once per series (duplicate attach → lifecycle_conflict). Requires a writable Pro seat; send an Idempotency-Key.

fieldinrequiredtype
seriesIdpathyesstring
studyIdbodyyesstring

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.

GET /v1/workspace/studies

List the workspace owner's studies with completed-response counts.

operationId: workspace.listStudies · method: kinetic.workspace_study_list · auth: scope: kinetic.workspace.read · risk: R0

Returns the studies visible to this workspace (the owner's studies), newest first, each with status, method, public_token, paid_at, entitlement_source, pro_subscription_id, and response_count (completed sessions). Use these study ids and their analysis snapshots as evidence for scenarios via kinetic.evidence_link.

No inputs.

Errors use the stable envelope (error.code, retryable): 400/403/404/409/402/429/502/401.