Developer guide

Funnel integration

The Funnel is already configured. Request a decision with the standard SDK, then validate the result before using it.

01Call the Funnel

Add the API URL, server Key, App ID and Funnel ID we provide to your backend. Use the agreed SDK version and start in Sandbox.

Node.js · Server only
import { createFunnelCampaignClient } from "@tinkerlandai/indiana-sdk/server";

const funnel = createFunnelCampaignClient({
  baseUrl: process.env.INDIANA_API_URL,
  apiKey: process.env.INDIANA_API_KEY,
  scope: {
    projectId: process.env.INDIANA_PROJECT_ID,
    environment: "sandbox",
  },
  funnelId: process.env.INDIANA_FUNNEL_ID,
});

export async function getOffer(input) {
  const decision = await funnel.decide({
    requestId: input.requestId,
    customer: {
      type: "externalUserId",
      value: input.userId,
    },
    attributes: {
      is_new_paying_user: input.isNewPayingUser,
      channel: input.channel,
      country: input.country,
    },
  });
  return decision;
}

Read user and attribution data on your backend. Persist a UUID requestId and the full input before sending; reuse both for retries.

02Use the result

Read decision.value and match offers by plan_id. Apply the result through your existing UI and checkout.

decision.value · Example excerpt
{
  "discount_offers": [
    {
      "plan_id": "plus_first_month",
      "discount_rate": 15
    },
    {
      "plan_id": "pro_first_month",
      "discount_rate": 20
    },
    {
      "plan_id": "wonder_first_month",
      "discount_rate": 25
    }
  ]
}

A discount_rate of 20 means 20% off. The campaign entry reuses the user's accepted decision for this Funnel.

03Validate before applying

User identity
Use the signed-in user and trusted payment history. Refunded purchases still count as prior payment. Keep the server Key off the frontend.
Decision result
Check the returned user, output structure, allowed plan IDs and agreed discount range. Use regular pricing when no offer applies or the request fails.
Checkout
Recheck eligibility, product and offer validity on your backend. Verify the actual first charge and renewal price; do not apply the annual discount twice.
Payment status
Confirm payment and access from authoritative server-side records. A redirect or Funnel completion alone is not proof of payment. Fetch a fresh result after account switching.

Before rollout, check an eligible new user, an ineligible user and a previous payer. Also verify a timeout retry and the actual checkout quote.