Skip to content
Indiana
Dashboard
Docs
Browse docs / Server client

Server client

Manage Customer sessions, mutate balances, resolve configuration and initiate purchases.

SDK examples target the current API. Check matching SDK versions and HTTP alternatives

API v1Updated

Server SDK

This reference targets protocol 0.5. See version information for SDK availability and HTTP examples.

Related:Versions and integration

Keep the Server Key on your host backend. baseUrl and scope identify the App/environment; every request checks credential permissions. Each Funnel owns its evaluation mode: new Funnels default to Local, and Owners/Admins can switch to Remote in Funnel settings. One API key can call different modes. Read the target mode with createFunnelDecisionClient({baseUrl, scope, apiKey, funnelId}).configuration(): use features() or evaluateFunnelNode() for Local, and decide()/submit() for Remote. The SDK has no remoteEval override.

Related:Server API key authentication and rotation

The Invoice SDK methods listed here are available in npm 0.5.0; npm 0.4.0 does not export them. The server and database must match protocol 0.5. SDK publication and server deployment are separate.

Current exports and methods

  • listInvoiceTemplates({ cursor? })

    Permissionsbilling:read

    Read invoice templates scoped to the App and environment.

    Returns { templates }

  • previewInvoice({ customerId, params })

    Permissionsbilling:write

    Preview invoice amounts and line items without creating a Stripe invoice.

    Returns { preview }

  • createInvoice({ customerId, requestId, params })

    Permissionsbilling:write

    Accept a durable invoice command. Reuse requestId on retries and read the operation result.

    Returns { operation }

  • manageInvoice({ customerId, command })

    Permissionsbilling:write

    Update, finalize, pay, void or reissue an invoice using a durable idempotency key.

    Returns { operation }

  • readInvoiceOperation({ customerId, taskId })

    Permissionsbilling:read

    Read the state, invoice reference or error of an asynchronous invoice command.

    Returns { operation }

  • listInvoices({ customerId, cursor? })

    Permissionsbilling:read

    Read a page of invoices for the selected Customer.

    Returns { invoices }

  • getInvoice({ customerId, invoiceId })

    Permissionsbilling:read

    Read an invoice, its line items and related operations.

    Returns { invoice }

  • getFeatures()

    Permissionsfeatures:read

    Read local flag definitions and remote flag keys. List groups contain hashes; remote rules stay on the server.

    Returns { payload }

  • evaluateFeatures({ attributes, features?, customerId? })

    Permissionsfeatures:read

    Evaluate only flags configured for server evaluation. A selected Customer supplies verified identity and stored attributes; the server records exposures. Clients cannot override the flag's evaluation location.

    Returns { features, generation, expiresAt }

  • trackEvents({ customerId?, events })

    Permissionsevents:write

    Send up to 100 analytics events with eventUuid, timestamp, name and properties. Reuse eventUuid after a lost response. Analytics events never establish payment or authorization facts.

    Returns { inserted, duplicates, rejected, skipped }

  • resolvePaywall({ customerId?, selector, locale, commerce, requirement? })

    Permissionsentitlements:read

    Resolve the independent Paywall, pinned Offering Version and current presentation capabilities without a Funnel or purchase.

    Returns { paywall }

  • setupPayment({ customerId, requestId, currency, makeDefault })

    Permissionsbilling:write

    Create a standalone card setup, without a subscription, entitlement or usage billing consent.

    Returns { setup }

  • readPaymentSetup({ customerId, setupId })

    Permissionsbilling:read

    Verify the actual provider result of the original setup without duplicate charges.

    Returns { setup }

  • listSubscriptions({ customerId?, entityId?, productId?, provider?, status?, cursor?, limit? })

    Permissionsbilling:read

    Page subscriptions by provider and cursor, retaining each provider contract.

    Returns { subscriptions }

  • listPurchases({ customerId?, entityId?, productId?, provider?, status?, cursor?, limit? })

    Permissionsbilling:read

    Read verified purchase history and original amounts; history does not imply current entitlement.

    Returns { purchases }

  • listSubscriptionConflicts({ customerId?, status?, cursor?, limit? })

    Permissionsbilling:read

    Read verified purchase conflicts and the memberships blocking an exclusive main plan.

    Returns { conflicts }

  • retrySubscriptionConflict({ customerId, orderId })

    Permissionsbilling:write

    Retry the original delivery, returning blocked if blockers remain, without another payment.

    Returns { resolution }

  • manageSubscriptionTrial({ customerId, requestId, action, reason, ...trialParameters })

    Permissionsbilling:write

    Start, extend or end a trial; Indiana runs no-card trials, and Stripe subscription trials return execution instructions that take effect once the webhook is recorded.

    Returns { trial }

  • readSubscriptionTrial({ customerId, operationId })

    Permissionsbilling:read

    Recover the original trial operation, reconciling Stripe when needed and retaining activation evidence.

    Returns { trial }

  • previewSubscriptionBatch({ customerId, requestId, targets })

    Permissionsbilling:write

    Quote by actual provider container; continue with the original request while ready is false.

    Returns { batch }

  • confirmSubscriptionBatch({ customerId, batchId })

    Permissionsbilling:write

    Accept frozen targets, retaining successful groups and recovering unfinished ones; partial is not complete.

    Returns { batch }

  • readSubscriptionBatch({ customerId, batchId })

    Permissionsbilling:read

    Read each original group state without accepting a quote or issuing another provider operation.

    Returns { batch }

  • abandonSubscriptionBatch({ customerId, batchId })

    Permissionsbilling:write

    Abandon only an unaccepted batch; submitted provider operations retain their original recovery tasks.

    Returns { batch }

  • verifySubscriptions({ customerId })

    Permissionsbilling:read

    Compare the customer's recorded products with Stripe Sandbox subscriptions (only when Indiana runs payments). Returns consistency, drift or incomplete evidence without charging or repairing.

    Returns { verification }

  • previewRefund({ customerId, requestId, invoiceId, mode, amountMinor, entitlementAction })

    Permissionsbilling:read

    Quote a refund of the customer's paid Stripe invoice: full refunds the remaining refundable amount, partial refunds amountMinor. A refund changes no plans unless entitlementAction is revoke, which also ends the plans the invoice paid for. The quote holds the amount and does not call Stripe.

    Returns { quote }

  • refund({ customerId, operationId })

    Permissionsbilling:write

    Confirm the refund. Where Indiana runs payments it creates the Stripe refund once with your connected key; where your backend runs payments the operation returns execution instructions, and your backend refunds in Stripe with their metadata and idempotency key. The refunded amount is recorded when Stripe's refund notification arrives; retries return the same operation.

    Returns { operation }

  • readRefund({ customerId, operationId })

    Permissionsbilling:read

    Read the refund operation's status (quoted, pending, succeeded, failed, expired) without creating a refund.

    Returns { operation }

  • readBillingInvoice({ customerId, invoiceId, after, limit })

    Permissionsbilling:read

    Page through all verified invoice items with nextCursor, without charging.

    Returns { detail }

  • readCreditStatement({ customerId, from, to, entityId?, snapshotAt, after, limit })

    Permissionscredits:read

    Up to 366 days. The first page uses null snapshotAt/after; subsequent pages retain the original snapshot and complete cursor.

    Returns { statement }

  • previewUpdate({ customerId, requestId, membershipId, timing, change })

    Permissionsbilling:read

    Quote a plan, seat or cancellation change for a membership billed by a Stripe subscription; upgrades are immediate and prorated, downgrades take effect at the end of the cycle.

    Returns { quote }

  • update({ customerId, operationId })

    Permissionsbilling:write

    Confirm the quote: Indiana execution runs it once in Stripe; record-only mode returns the Stripe instructions for the merchant.

    Returns { operation }

  • readSubscriptionUpdate({ customerId, operationId })

    Permissionsbilling:read

    Read the change status; a booked downgrade or cancellation is scheduled until it takes effect.

    Returns { operation }

  • manageBalanceGrant({ customerId, command })

    Permissionscredits:manage

    Create recurring or one-time grants, adjust remaining balances, change expiry or revoke a rule with requestId and revision. Requires server credits:manage; payment facts remain immutable.

    Returns { grant }

  • listBalanceGrants({ customerId, after, limit })

    Permissionscredits:read

    Read customer and Entity grants with available, held and spent balances. Page with nextCursor and a maximum limit of 100.

    Returns { grants }

  • previewAttach({ customerId, entityId?, requestId, plans, provider, currency, offerId? })

    Permissionsbilling:read

    Save a fixed quote for an explicit customer without initiating payment; reuse requestId on retries. Independent execution supports one Stripe or free plan, or multiple paid Stripe plans on one connection, currency and billing interval, without multi-plan trials or seats.

    Returns { quote }

  • attach({ customerId, operationId })

    Permissionsbilling:write

    Confirm after the customer reviews and accepts the quote. Retries reuse operationId and the original order without a Funnel.

    Returns { operation }

  • restoreNativePurchase({ customerId, requestId, provider, purchaseIntentId, productId, signedTransaction?, purchaseToken? })

    Permissionsbilling:write

    Recover the same purchase and delivery from verified store facts without issuing credits twice.

    Returns { restore }

  • readAiPricing({ internal_feature_id })

    Permissionscredits:read

    Read current model prices and markups.

    Returns { configuration }

  • readBalanceSource({ customerId, sourceId })

    Permissionscredits:read

    Read available, held and spent funds in the plan's current window.

    Returns { balance }

  • adjustBalance({ customerId, command })

    Permissionscredits:manage

    Add, subtract or set plan funds after checking expectedAvailable; retry the same requestId.

    Returns { balance }

  • readUsage({ customerId, query })

    Permissionscredits:read

    Read capacity and actual non-consumable usage.

    Returns { usage }

  • setUsage({ customerId, command })

    Permissionscredits:manage

    Atomically synchronize actual usage with expectedRevision, including decreases and usage above capacity.

    Returns { usage }

  • readSubscriptionOperation({ customerId, operationId })

    Permissionsbilling:read

    Recover payment and delivery for an accepted operation without creating another provider attempt.

    Returns { operation }

  • manageBillingLimits({ customerId, command })

    Permissionsbilling:write

    The trusted server sets customer or Entity usage limits, alerts or control: overage policies with an idempotent requestId. Overage policies contain allowed, overageLimit, skipOverageBilling and a UTC window. Entity policies override customer policies; removal restores inheritance. Customers still confirm payment consent.

    Returns { controls }

  • getOrCreateCustomer(input)

    Permissionscustomers:write

    Find or create a customer by the host-verified externalUserId. Retries do not overwrite existing profiles; email is not identity. The optional fingerprint is a stable deduplication signal supplied by your host, such as a device identifier. The SDK does not collect it; only an environment-scoped hash is kept and the first supplied value is never replaced. Without it, trials deduplicate by Customer only. You can also reserve a customer with only an email (for example, a contract signed before sign-up). When that user signs up, calling with an externalUserId and the same email claims the reservation in place, keeping its plans and balances. Only send verified emails; otherwise someone else could claim the reservation.

    Returns { customer, created }

  • getCustomer({ lookup }) / listCustomers(filters)

    Permissionscustomers:read

    Look up an explicit id or externalUserId; listing applies current customer filters before pagination.

    Returns Customer response

  • updateCustomer({ lookup, requestId, patch })

    Permissionscustomers:write

    Update supplied profile fields and attributes. Use removeAttributes to delete keys and tagChanges for tags. Submit changed fields only and retain the original requestId for retries.

    Returns Customer response

  • createCustomerSession(customerId)

    Permissionssessions:create

    Issue a short-lived session for the Indiana customer mapped to the host's verified login. Do not derive identity from browser parameters.

    Returns { customerToken, expiresAt }

  • renewCustomerSession(input) / revokeCustomerSessions(input)

    Permissionssessions:create

    Recheck host authentication before renewal or revocation. Revocation requires sessions:create; reset clears SDK memory only.

    Returns Session response

  • createGuestToken()

    Generate a guest proof on your backend, retain it in an HttpOnly cookie and reuse it for creation retries.

    Returns gg_gc_ token

  • createGuestCustomer(input) / resumeGuestSession(input) / claimGuestCustomer(input)

    Permissionssessions:create

    Guest creation, recovery and claiming require their respective session or customers:write permissions. Derive the claimed externalUserId from verified login; authenticate before store purchases. Guest creation accepts a fingerprint. Login to an existing Customer returns switched=true: create its session and start a new Funnel. Each Customer retains its profile, device and history.

    Returns Guest/session response

  • resolveOffering({ customerId, selector, commerce, requirement? })

    Permissionsentitlements:read

    Resolve a published Offering hierarchy and per-Product availability without creating a Funnel or UI. Purchase independently through previewAttach/attach. Preserve the Offering Version and follow explicit unavailable reasons.

    Returns { offering, candidates, availability, check }

  • checkEntitlement({ customerId, requirement, commerce?, paywallId? })

    Permissionsentitlements:read

    Available in npm 0.1.0 beta with a matching server deployment. Check access and recommend products without consumption or automatic payment. Derive customerId from verified host authentication.

    Returns { check }

  • readHoldings({ customerId })

    Permissionsentitlements:read

    Read current memberships and balances. Decimal quantities remain strings and existing memberships retain their contract versions.

    Returns { holdings }

  • readLedger({ customerId, query })

    Permissionscredits:read

    Filter all history before pagination. Preserve the entire nextCursor and clear it when filters change.

    Returns { ledger }

  • quoteBalance({ customerId, command })

    Permissionscredits:read

    command.operation is quote. A quote does not spend funds or replace atomic consumption.

    Returns { quote }

  • mutateBalance({ customerId, command })

    Permissionscredits:consume

    Consume, reserve, confirm, release or refund at the original rate. Retain each action's original idempotencyKey and input; refunds also require credits:manage.

    Returns { receipt }

  • trackUsage({ customerId, command })

    Permissionscredits:consume

    Consume features mapped to eventName or a specific internal_feature_id; choose one target type. Derive the customer identity on the trusted backend, retain the original idempotencyKey and input for retries, and inspect each receipt's accepted status.

    Returns { receipts }

  • readSeats(input) / manageSeat(input)

    Permissionscustomers:read

    Read purchased capacity and assign identified members. Assignments require billing:write; billed capacity changes are confirmed through Funnel nodes.

    Returns Seat response

  • manageUsageEntity(input) / readCreditAnalytics(input) / readUsageAnalytics(input)

    Permissionscredits:manage

    Manage usage scope for a verified customer. Analytics requires credits:read; client-supplied payer identity does not authorize access.

    Returns Usage entity / analytics response

  • submitUsageBatch(input) / readUsageBatch(input)

    Permissionscredits:consume

    Persist processing with an independent idempotent receipt per item. Reading progress requires credits:read.

    Returns Batch response

  • grantOffer({ customerId, couponId, requestId })

    Permissionsoffers:grant

    Trusted backends use offers:grant and the merchant customerId. The source Customer SDK provides claimCoupon(couponId, requestId) with offers:resolve for self-claim-enabled Coupons; Local Funnel uses the same Coupon API. Indiana checks scope, eligibility and limits. Retain requestId on retry.

    Returns Offer response

  • recordCouponRedemption({ customerId, eventId, grantId, productVersionId, subscriptionId, occurredAt })

    Permissionsbilling:write

    Available in the source SDK; published0.3.1 uses the corresponding HTTP endpoint. Report after your trusted backend confirms payment with billing:write; retain eventId and all facts on retry. The merchant receipt consumes the held Grant, creates no subscription or entitlement, and does not keep Funnel waiting for payment.

    Returns Merchant Coupon receipt response

AI model pricing

  • createConfiguredAiPricing(client, { entitlementId })

    Permissionscredits:read

    Read current model prices and markups for the App/environment. Recreate pricing after saving configuration; saved quotes are not repriced. See the AI token guide for integration and recovery.

    Returns Promise<AI pricing helper>

  • createOpenRouterUsageClient({ openRouter, pricing, client, reasoning, context, persist, mapTokens? }) / trackOpenRouterUsage(input)

    Import from the separate /openrouter entry and install @openrouter/sdk in the host. Wrap chat.send, persisting actual usage and the frozen quote before atomic settlement. Recover with the original generationId, usage, quote and idempotency key without rerunning the model.

    Returns OpenRouter client / persisted usage record

  • createAiUsageMiddleware({ pricing, client, modelId, reasoning, context, persist, mapTokens? })

    AI SDK v7 captures final usage for generate and streaming. context supplies a durable unique key per provider call or tool step; persist saves actual usage and the frozen quote before balance consumption. Interrupted usage is not estimated. Settlement failure is explicit; retry the original quote without rerunning the model.

    Returns LanguageModelV4Middleware

  • createAiPricing(options?)

    Trusted server only. Read current model prices from Models.dev with a 15-minute cache. Configure default, provider and model markups or custom model prices. The metered entitlement must use one micro USD; a fixed credit rate converts the cost.

    Returns AI pricing helper

  • pricing.quoteTokens({ modelId, tokens })

    Supply seven mutually exclusive token pools, using zero for unused pools. Freeze rates, context tier, markup, quantity and hash. Missing required prices are rejected. Explicit free prices retain real tokens in zero-cost events. Persist the original quote for job retries.

    Returns Promise<AiTokenQuote>

  • pricing.trackTokens(client, { customerId, internal_feature_id, entityId?, idempotencyKey, quote, properties? })

    Permissionscredits:consume

    Validate the frozen quote and record tokens and model rates in one atomic balance mutation. Reuse the quote and idempotency key for retries; refunds use the original consumption price. Supply actual usage manually or capture it with createAiUsageMiddleware.

    Returns Promise<Balance mutation response>

  • pricing.refreshPrices()

    Clear the price cache so the next quote reloads prices. Saved quotes, consumption and refunds retain their original rates.

    Returns void

  • aiTokenQuoteSchema.parse(value) / aiPriceSnapshotSchema.parse(value)

    Validate a persisted current quote or price snapshot without calling a model or changing a balance.

    Returns Validated quote / price snapshot

Funnel and store recovery

  • createFunnelDecisionClient(options).submit(input) / decide(input) / read(decisionId) / reportUsed(input)

    Trusted backend with sessions:create and funnels:run. customer is { type: "id" } (an Indiana Customer ID) or { type: "externalUserId" } (your user ID; a missing Customer is created with the decision, needs customers:write and may carry creation-only customerData). Fix customer, Funnel and original requestId. submit returns without waiting; decide waits up to 30 seconds. Retry original input when acceptance is unknown; read the original decisionId when accepted but pending. reportUsed records a caller report without issuing or charging.

    Returns Decision status / decision / usage report

  • createFunnelOrchestrationClient(options).signal(input) / readResults(runId)

    Backend sessions:create and funnels:run only. Send declared custom receipts, retaining eventId and data for retries. Acknowledgement is not consumption. Read completed task and consumed receipt results; custom receipts cannot confirm payment.

    Returns Receipt acknowledgement / node results

  • renewFunnelRun(options, { runId, customerId })

    A backend with sessions:create and funnels:run renews the credential for the same identified customer without extending runExpiresAt. Browsers cannot renew it or change customer identity.

    Returns Renewed run credential

  • createPaywallStartClient(options).start({ paywallId, requirement?, ...input })

    Available in npm 0.1.0 beta. With a matching server, persist original input and requestId on the backend with a customer session and explicit provider/currency. requirement is frozen for the run while retaining the authored Paywall version.

    Returns FunnelRuntimeResponse

  • createFunnelStartClient(options).start(input)

    Persist the original start input and requestId. A server Key uses customer: { type: 'id' | 'externalUserId', value }; creation-only customerData requires an externalUserId reference and customers:write. Use the returned customerId to issue a session with sessions:create. Customer-credential starts name no customer. Standalone Paywall uses its own session; the old start-body customerToken is rejected.

    Returns FunnelRuntimeResponse

  • createFunnelCampaignClient(options).decide(input) / start(input)

    Invoke campaigns explicitly from a trusted backend. Both decide/start use a customer reference; start requires cooldownSeconds. Frequency or in-progress suppression returns suppressed and retryAt without a fake Run. Report shown only after actual presentation. Customer and Run credentials cannot replace the server Key.

    Returns FunnelDecision / FunnelCampaignStartResponse

  • createNativeReceiptClient(options).recover(command)

    Current orders only: use a backend Key plus the current Customer session through subscriptions/native/restore to submit evidence or read the accepted operation. orderId and receiptId must identify the same commercial intent. Recovery does not rely on runToken or advance an old run. Requires billing:write and funnels:run. See the native guides for store availability.

    Returns NativeReceiptResponse