invitation.dev / docs / merchants

launch one referral program

Create a draft, configure the full contract, prove one no-credit conversion, then activate. The only required human step in the agent-driven path is minting the org-bound key.

Package source and API contracts exist in the repository. Registry publication, deployment flags, database state, and a hosted campaign still need verification on the environment you target.

# before you start

Key, org, and runtime

Management stays on invitation.app

Create or select the organization in the business console. Mint a key with write and org:campaigns, bound to that organization; keep the raw value out of source, screenshots, and logs.

The target must opt in

MCP requires FEATURE_AGENT_API. Merchant surfaces also require FEATURE_ORGS and FEATURE_CAMPAIGNS. A 404 while the flag is off is a gate failure, not evidence that the endpoint path changed.

~/.mcp.json
{
  "mcpServers": {
    "invitation": {
      "type": "http",
      "url": "https://api3.invitation.codes/api/mcp",
      "headers": {
        "Authorization": "Bearer invt_..."
      }
    }
  }
}

Connect to https://api3.invitation.codes/api/mcp, then call tools/list. Do not assume a tool is enabled merely because this quickstart documents its stable contract.

# create + configure

A draft is not a configured campaign

install
pnpm add @invitation/node @invitation/tracker
create-campaign.ts
import { InvitationNodeClient } from "@invitation/node";

const invitation = new InvitationNodeClient({
  apiKey: process.env.INVITATION_API_KEY!,
});

const campaign = await invitation.campaigns.create({
  name: "Summer launch",
  websiteUrl: "https://merchant.example",
  rewardAmount: 500,
  rewardType: "fixed_coins",
  rewardTrigger: "purchase",
  doubleSided: true,
  refereeRewardAmount: 250,
  allowAgents: false,
  autoApproveConversions: false,
});
configure-campaign.ts
await invitation.campaigns.update({
  slug: campaign.slug,
  validationMethod: "sdk_api",
  rewardSplitMode: "both_users",
  rewardSplitRatio: 50,
  budgetLimitCoins: 100000,
  allowAgents: false,
  autoApproveConversions: false,
});

Why two calls?

The current create contract accepts core reward fields; validationMethod, rewardSplitMode, budget, webhook, and approval settings are applied by update. Keep this seam visible until the public write contract is unified.

# tracking

Capture the session before reporting the conversion

The browser tracker captures ?ref=CODE, registers the click, and stores the server-issued session token. Send the conversion from the browser or your server only after that session exists.

browser.ts
import { InvitationTracker } from "@invitation/tracker";

const tracker = new InvitationTracker({ campaignId: "campaign-id" });
tracker.init(); // Run in a browser after the page loads with ?ref=CODE.

await tracker.trackPurchase({
  orderId: "order_test_1042",
  amount: 12900,
  currency: "USD",
  email: "buyer@example.com",
  testMode: true,
});
server.ts
await invitation.conversions.track({
  campaignId: campaign.id,
  sessionToken: request.cookies.invt_session,
  conversionType: "purchase",
  orderId: "order_test_1042",
  amount: 12900,
  currency: "USD",
  email: "buyer@example.com",
  testMode: true,
});

The canonical hosted bundle is https://api3.invitation.codes/api/v3/referral/tracker.js. If it returns 503, the deployment does not carry the built artifact. Keep testMode: true until the console shows the complete path.

# activate

Return resolved URLs, not guessed ones

Activate only after the configured draft is reviewable. Activation is wired to create or link a directory program, but the directory URL is runtime output: print the value returned by the target rather than manufacturing a demo slug.

activate.ts
const active = await invitation.campaigns.activate(campaign.id);

console.log({
  console: "https://invitation.app/business/campaigns/" + active.slug,
  directory: active.directoryUrl ?? "runtime proof pending",
});

Continue management at invitation.app/business. invitation.dev remains a static documentation surface.

# exit check

Evidence before the word live

  1. 01The key has write + org:campaigns and is bound to the intended organization.
  2. 02The draft shows the expected reward, validation, split, budget, and approval terms.
  3. 03A real referral URL creates a browser attribution session; a made-up token is not proof.
  4. 04A testMode conversion appears in the campaign console and credits no reward.
  5. 05Activation succeeds and the returned invitation.codes program URL resolves.

Integration status

SDK/browser tracking is the runnable contract. Stripe is a supported validation value but still needs a merchant-specific staging proof. Shopify is planned and is not a ready quickstart.