← Partner Fit
API
Tokens

Run Partner Fit from your own code

Both metered lanes are available over HTTP and each returns one JSON object. The division of labour: the page reads every candidate's demand evidence, places each on the depth ladder, ranks the portfolio, the ladder and where the function reports, and checks certification renewals, attribution plumbing and comp, then hands it all to the run as facts. The run writes the partnership portfolio or the attribution rules; the page then holds it to its own facts (pfreply.js).

Base URL and the response shape

Every endpoint lives under https://api.skillsafe.ai/v1/app-api, and every response has one shape:

{ "ok": true,  "data":  { ... } }
{ "ok": false, "error": { "code": "...", "message": "..." } }

The token is minted for this app (the guest call takes {"slug":"partner-fit"}), so no slug header is needed afterwards. Send it as Authorization: Bearer YOUR_TOKEN. The run body is the input object, sent bare.

StatusCodeMeaning
400validation_errorThe body is not a JSON object, or a required key (task, company, partners, facts) is missing. The page always sends all five of task, company, partners, carry, facts; carry is an empty string for portfolio.
401unauthorizedNo token, or a stale one. Mint a guest token or sign in again.
402insufficient_creditsThe balance is under min_credits. Price with /estimate first.
403forbiddenA guest token tried to run: both lanes are metered and need a personal sign-in.
404not_foundUnknown job id.
429rate_limitedBack off and retry.
5xxserver_errorTransient. Retry with the same Idempotency-Key so a retry never double-bills.

The task field comes first

Two lanes, chosen by task, in the order the work runs - for the partnerships lead, then for RevOps and finance:

A missing or unknown task is answered as portfolio. Both lanes send the same five fields. The facts are the page's checks, one row per line, and a line starting "must:" is a rule the reply has to hold. The page's handoff carries the portfolio into carry for the attribution lane.

The input

FieldRequiredWhat
taskyesportfolio or attribution. If it is missing or neither, do portfolio and set "task": "portfolio".
companyyesthe company and what prompted this, the program today, the demand data, where partnerships report, the sponsor, size, the business model, the attribution plumbing today, the deadline and the mandate; "not given" means not given.
partnersyeseach candidate partner with its evidence line and the page's reading of it, blocked deals, joint economics, the proposed rung and the page's rung; then the certification joins planned.
carrysend it (empty for portfolio)attribution task only: the portfolio decisions, when the portfolio task ran first; may be empty.
factsyesthe page's checks, one line each as area | id | status | evidence, the verdict and the rankings. A line starting "must:" applies to your reply.
retry_notenooptional; if present, your previous reply was unusable - follow it.

The rules the model applies

From the source skill, @samber/integration-partnership-strategy - the only standard the run applies:

House rules

The replies

portfolio

Write the partnership portfolio the partnerships lead will run.

  1. summary - one sentence, at most 40 words: the portfolio shape, and the first thing that must change.
  2. portfolio - shape (fewdeep, breadth or anchor, exactly as the facts rank first), why (one sentence naming the moves).
  3. shortlist - one object per candidate partner in the input, no others: partner (as named), evidence (its demand-evidence line, from the input; empty for a parked partner), rung (park, referral, reseller, cosell, cobuild or oem, exactly the page's rung), next (one sentence: the condition that moves it one rung deeper on the ladder itself - referral, reseller, co-sell, co-build, OEM, not the ranked order in the facts - or, for a parked partner, the evidence that would un-park it).
  4. governance - one object per partner at cobuild or oem, no others ([] when none): partner, cadence (how often the two sides sync - at least quarterly, labelled proposed when the input gives none), plan (one sentence: the joint business plan's shared targets and which side carries the heavier lift now), qbr (one sentence: the role on each side with authority to approve resources - proposed when the input names none - and what it reviews).
  5. certifications - one object per certification join in the input ([] when none): platform, owner (the renewal owner, as the input names one or proposed), cost (the standing cost a quarter - the input's hours, or proposed), cadence (how often it renews).
  6. org - placement (sales, product or alliances, exactly as the facts rank first), why (one sentence), roles (short strings: the roles the function staffs - the split roles when the company is past about 100 employees; else []).
  7. kpis - at least three short strings.
  8. caveats - at most 4 short strings; [] when there is nothing to say.
{
  "task": "portfolio",
  "summary": "one sentence",
  "portfolio": { "shape": "fewdeep", "why": "one sentence" },
  "shortlist": [ { "partner": "as named", "evidence": "the evidence line", "rung": "cosell", "next": "one sentence" } ],
  "governance": [ ],
  "certifications": [ { "platform": "as named", "owner": "a role", "cost": "a cost", "cadence": "a cadence" } ],
  "org": { "placement": "sales", "why": "one sentence", "roles": [ ] },
  "kpis": [ "a measure" ],
  "caveats": [ ]
}

The page holds it to its own facts (check() in pfreply.js; any warning makes the reply flagged): the reply answers the task it was sent; no web link; no backticks; a summary of at most 40 words; the ranked portfolio shape; every candidate on the shortlist and no other, each at the page's rung with its evidence line and the condition for its next move; governance with a cadence of at least quarterly, a joint plan and the QBR for every co-build or OEM partner and no other; every planned certification with a renewal owner and a standing cost; the ranked org placement, with the split roles past about 100 employees; at least three measures.

attribution

Write the attribution rules RevOps will build into the CRM.

  1. summary - one sentence, at most 40 words.
  2. definitions - sourced and influenced: one sentence each, in this company's own deal terms.
  3. claim - field (one sentence: the partner-source field on the CRM opportunity and the dated claim ID), timing (one sentence: claimed at deal creation, never at close), window (a number of days - the input's when it gives one of 30 or fewer, else about 14, proposed).
  4. caps - sourced and influenced: one sentence each - how each is capped (a share of the quarter's bookings or a dollar ceiling), set before the quarter, labelled proposed when the input gives none.
  5. motions - one object per rung the facts list as in use, no others: rung (as the facts spell it), rule (one sentence: how a deal on that motion is claimed and credited, including one sourced partner per deal where it applies).
  6. comp - one sentence: how AE pay on partner deals is equalized with direct deals.
  7. forecast - one sentence: how partner pipeline joins the same forecast review with the same exit criteria.
  8. kpis - at least four short strings: sourced against influenced revenue, activation rate, time to first deal, partner CAC against direct CAC.
  9. caveats - at most 4 short strings; [] when there is nothing to say.
{
  "task": "attribution",
  "summary": "one sentence",
  "definitions": { "sourced": "one sentence", "influenced": "one sentence" },
  "claim": { "field": "one sentence", "timing": "one sentence", "window": "14 days (proposed)" },
  "caps": { "sourced": "one sentence", "influenced": "one sentence" },
  "motions": [ { "rung": "cosell", "rule": "one sentence" } ],
  "comp": "one sentence",
  "forecast": "one sentence",
  "kpis": [ "a measure" ],
  "caveats": [ ]
}

The page requires: the reply answers the task it was sent; the same text rules; sourced and influenced defined separately; the claim on the CRM opportunity, at deal creation, inside a window of 30 days or fewer; both caps; one sourced partner per deal; a rule for each rung in use and none for unused rungs; equal AE comp; one forecast review; measures for sourced against influenced revenue, activation rate, time to first deal and partner CAC against direct CAC.

Worked examples

Three runs from the page's free samples (invented companies): the portfolio for a contract SaaS with a vibes shortlist, the attribution rules for the same company carrying that portfolio, and the portfolio for a field-service platform whose program holds. Each input is exactly what the page sends; each reply is the saved reply the sample replays, shipped unedited - but the facts and long strings are shortened in this display only, and every cut is listed under the example. The last line is the page's own check of the full reply.

portfolio - A contract SaaS with 40 integrations and a vibes shortlist

The page read it as: partners picked on relationships - evidence first; portfolio fewdeep, breadth, anchor; org sales, product, alliances; rungs Salesforce cosell, DocuSign cosell, HubSpot cosell, Brieflyne AI park, Slack park; 0 of 5 gates; failing checks: evidence, graduation, renewals, attribution, comp.

Input (facts is 2352 characters; the first 1397 are shown):

{
 "task": "portfolio",
 "company": "Company: Clausewick\nThe product and what prompted this: Contract-management SaaS for mid-market legal teams; 40 integrations are listed, none produces pipeline, and the board asked which five partners actually matter.\nProgram today: Dozens of listed integrations, no depth strategy; demand data: A partner-source field on CRM opportunities; partnerships report to: Sales; executive sponsor: Interest but no budget; employees: 60\nThe business model supports partner-transacted deals: no; one platform dominates the customer base: no; partner-sourced revenue is a board metric: no; productizing integrations is the goal: no\nAttribution today: CRM partner-source field yes; one blended partner-touched number; claimed at close; caps set before the quarter no; window not given; AE comp equal on partner deals no; one forecast review yes\nHard deadline: no; a compounding asset; effort ceiling: medium; as-of: 2026-11-01",
 "partners": "Candidate partners (partner | evidence | blocked deals | joint economics | proposed rung | the page's rung):\n- Salesforce | evidence: 38% of customers run it; 9 lost deals in 2026 named the missing integration (numeric) | blocked deals $640k | joint economics unproven | proposed co-build | page rung cosell\n- DocuSign | evidence: 212 support requests a year for e-signature sync (numeric) | blocked deals $90k | joint economics unproven | proposed co-sell | page rung cosell\n- HubSpot | evidence: 14 open deals blocked on the connector (numeric) | blocked deals $310k | joint economics unproven | proposed co-sell | page rung cosell\n- Brieflyne AI | evidence: our CEO knows their founder (not demand evidence) | joint economics unproven | proposed co-build | page rung park\n- Slack | evidence: everyone uses it (not demand evidence) | joint economics unproven | proposed referral | page rung park\n\nCertification joins planned (platform | renewal owner | budget | cadence):\n- Salesforce AppExchange security review | renewal owner none | no budgeted hours | cadence annual",
 "carry": "",
 "facts": "The page's checks (5 fail, 2 warn, 0 pass, 4 n/a); verdict: partners picked on relationships - evidence first:\n- Portfolio and depth | shortlist | na | 5 partners: 3 with numeric evidence, 0 with a source but no numbers, 2 with none\n- Portfolio and depth | shape | na | Few-and-deep > Category-coverage breadth > Platform-anchor - dozens of listed integrations with no depth - concentrate on the few the evidence names\n- Portfolio and depth | evidence | fail | Brieflyne AI (\"our CEO knows their founder\" is not demand evidence); Slack (\"everyone uses it\" is not demand evidence) - parked until evidence exists\n- Portfolio and depth | graduation | fail | Salesforce proposed at co-build / strategic alliance - held at co-sell / integration alliance\n- Portfolio and depth | ladder | na | Co-sell / integration alliance > Referral > Co-build / strategic alliance > OEM / embed - the business model cannot support partner-transacted deals - the reseller rung is deleted, not parked\n- Certifications | renewals | fail | Salesforce AppExchange security review has no renewal owner and has no budgeted hours a quarter\n- Attribution | attribution | fail | one blended partner-touched number instead of sourced and influenced; attribution assigned at close instead of claimed at deal creation with a dated ID; no credit caps set before the quarter - uncapped influence is how partner revenue exceeds total\n\n[... 955 more characters cut from this display ...]"
}

Reply (long strings shortened for display - see the cuts below):

{
 "task": "portfolio",
 "summary": "Clausewick moves from 40 listed integrations to a few-and-deep portfolio of Salesforce, DocuSign and HubSpot at co-sell; first, name an owner and budgeted hours for the AppExchange security review before anything else is signed.",
 "portfolio": {
  "shape": "fewdeep",
  "why": "Concentrate on the three partners whose deals, requests and blocked pipeline are on record, run each as a co-sell motion, park Brieflyne AI and Slack, and stop maintaining the other listings as if they were partnerships."
 },
 "shortlist": [
  {
   "partner": "Salesforce",
   "evidence": "38% of customers run it; 9 lost deals in 2026 named the missing integration; $640k in blocked deals",
   "rung": "cosell",
   "next": "Moves to co-build once co-sold deals with Salesforce show proven joint economics, for example the first $640k of blocked pipeline closing with a Salesforce partner-source ID on each opportunity, alongside product, commercial and [... 17 more characters cut from this display]"
  },
  {
   "partner": "DocuSign",
   "evidence": "212 support requests a year for e-signature sync; $90k in blocked deals",
   "rung": "cosell",
   "next": "Moves to co-build once the maintained e-signature sync converts the $90k of blocked deals and the joint pipeline shows proven economics both sides sign off on."
  },
  {
   "partner": "HubSpot",
   "evidence": "14 open deals blocked on the connector; $310k in blocked deals",
   "rung": "cosell",
   "next": "Moves to co-build once the connector ships and a majority of the 14 blocked deals close as co-sold opportunities with proven joint economics."
  },
  {
   "partner": "Brieflyne AI",
   "evidence": "",
   "rung": "park",
   "next": "Un-parks only when CRM data names deals, request counts or a customer share for Brieflyne AI; the CEO's relationship with their founder does not count."
  },
  {
   "partner": "Slack",
   "evidence": "",
   "rung": "park",
   "next": "Un-parks when lost deals, support request counts or retention data tie a Slack integration to Clausewick revenue, not general usage."
  }
 ],
 "governance": [],
 "certifications": [
  {
   "platform": "Salesforce AppExchange security review",
   "owner": "Integration engineer (proposed)",
   "cost": "40 h a quarter (proposed)",
   "cadence": "annual"
  }
 ],
 "org": {
  "placement": "sales",
  "why": "Partnerships already report to Sales at 60 people, with no board metric on partner revenue and no productization goal, so the co-sell motions stay in the same pipeline and forecast as direct deals.",
  "roles": []
 },
 "kpis": [
  "Partner-sourced against partner-influenced revenue, reported as two numbers",
  "Activation rate: share of the three co-sell partners producing a lead or revenue each quarter",
  "Time to first co-sold deal per partner",
  "Partner CAC against direct CAC",
  "Blocked pipeline recovered: Salesforce $640k, HubSpot $310k, DocuSign $90k"
 ],
 "caveats": [
  "The AppExchange security review has no renewal owner and no budgeted hours today; do not sign until both are set.",
  "Attribution is one blended number assigned at close with no caps; the AE pay gap on partner deals will stall co-sell until fixed.",
  "The executive sponsor has interest but no budget; any later co-build step needs one."
 ]
}

Cut from this display only (the saved reply and the check use the full text): shortlist[0].next (245 characters, 228 shown).

What step 5 prints for it: Salesforce: cosell | DocuSign: cosell | HubSpot: cosell | Brieflyne AI: park | Slack: park

The page's check: kept - nothing to flag

attribution - A contract SaaS with 40 integrations and a vibes shortlist

The input carries the saved portfolio (R.laneForm fills carry from the portfolio reply), as the page's handoff does. Failing checks on the page: evidence, graduation, renewals, attribution, comp.

Input (facts is 2406 characters; the first 1397 are shown):

{
 "task": "attribution",
 "company": "Company: Clausewick\nThe product and what prompted this: Contract-management SaaS for mid-market legal teams; 40 integrations are listed, none produces pipeline, and the board asked which five partners actually matter.\nProgram today: Dozens of listed integrations, no depth strategy; demand data: A partner-source field on CRM opportunities; partnerships report to: Sales; executive sponsor: Interest but no budget; employees: 60\nThe business model supports partner-transacted deals: no; one platform dominates the customer base: no; partner-sourced revenue is a board metric: no; productizing integrations is the goal: no\nAttribution today: CRM partner-source field yes; one blended partner-touched number; claimed at close; caps set before the quarter no; window not given; AE comp equal on partner deals no; one forecast review yes\nHard deadline: no; a compounding asset; effort ceiling: medium; as-of: 2026-11-01",
 "partners": "Candidate partners (partner | evidence | blocked deals | joint economics | proposed rung | the page's rung):\n- Salesforce | evidence: 38% of customers run it; 9 lost deals in 2026 named the missing integration (numeric) | blocked deals $640k | joint economics unproven | proposed co-build | page rung cosell\n- DocuSign | evidence: 212 support requests a year for e-signature sync (numeric) | blocked deals $90k | joint economics unproven | proposed co-sell | page rung cosell\n- HubSpot | evidence: 14 open deals blocked on the connector (numeric) | blocked deals $310k | joint economics unproven | proposed co-sell | page rung cosell\n- Brieflyne AI | evidence: our CEO knows their founder (not demand evidence) | joint economics unproven | proposed co-build | page rung park\n- Slack | evidence: everyone uses it (not demand evidence) | joint economics unproven | proposed referral | page rung park\n\nCertification joins planned (platform | renewal owner | budget | cadence):\n- Salesforce AppExchange security review | renewal owner none | no budgeted hours | cadence annual",
 "carry": "Portfolio: Few-and-deep - Concentrate on the three partners whose deals, requests and blocked pipeline are on record, run each as a co-sell motion, park Brieflyne AI and Slack, and stop maintaining the other listings as if they were partnerships.\nRungs: Salesforce co-sell / integration alliance; DocuSign co-sell / integration alliance; HubSpot co-sell / integration alliance; Brieflyne AI parked - no demand evidence; Slack parked - no demand evidence\nThe function: Report into Sales",
 "facts": "The page's checks (5 fail, 2 warn, 0 pass, 4 n/a); verdict: partners picked on relationships - evidence first:\n- Portfolio and depth | shortlist | na | 5 partners: 3 with numeric evidence, 0 with a source but no numbers, 2 with none\n- Portfolio and depth | shape | na | Few-and-deep > Category-coverage breadth > Platform-anchor - dozens of listed integrations with no depth - concentrate on the few the evidence names\n- Portfolio and depth | evidence | fail | Brieflyne AI (\"our CEO knows their founder\" is not demand evidence); Slack (\"everyone uses it\" is not demand evidence) - parked until evidence exists\n- Portfolio and depth | graduation | fail | Salesforce proposed at co-build / strategic alliance - held at co-sell / integration alliance\n- Portfolio and depth | ladder | na | Co-sell / integration alliance > Referral > Co-build / strategic alliance > OEM / embed - the business model cannot support partner-transacted deals - the reseller rung is deleted, not parked\n- Certifications | renewals | fail | Salesforce AppExchange security review has no renewal owner and has no budgeted hours a quarter\n- Attribution | attribution | fail | one blended partner-touched number instead of sourced and influenced; attribution assigned at close instead of claimed at deal creation with a dated ID; no credit caps set before the quarter - uncapped influence is how partner revenue exceeds total\n\n[... 1009 more characters cut from this display ...]"
}

Reply:

{
 "task": "attribution",
 "summary": "Clausewick replaces its one blended partner-touched number, assigned at close, with capped sourced and influenced credit claimed at deal creation on the Salesforce, DocuSign and HubSpot co-sell motions, and equal AE pay.",
 "definitions": {
  "sourced": "A Clausewick opportunity counts as sourced when Salesforce, DocuSign or HubSpot brought the legal-team buyer and the deal would not exist without that partner.",
  "influenced": "An opportunity counts as influenced when the deal was already open and a partner materially advanced it, for example HubSpot unblocking one of the 14 connector-blocked deals."
 },
 "claim": {
  "field": "Add a required Partner Source picklist on the CRM opportunity, limited to the three co-sell partners, paired with a Partner Claim ID stamped with the claim date.",
  "timing": "The partner claim is entered when the opportunity is created and locked after the window, never added or changed at close.",
  "window": "14 days (proposed)"
 },
 "caps": {
  "sourced": "Partner-sourced credit is capped at 25% of new bookings per quarter (proposed), set in the plan before the quarter opens.",
  "influenced": "Partner-influenced credit is capped at 40% of new bookings per quarter (proposed), reported as its own number and never added to sourced."
 },
 "motions": [
  {
   "rung": "cosell",
   "rule": "A co-sell deal carries one sourced partner per deal, chosen from Salesforce, DocuSign or HubSpot at creation, while any other of the three that advanced it is logged as influenced only."
  }
 ],
 "comp": "AEs earn the same quota credit and commission rate on a Salesforce, DocuSign or HubSpot co-sell deal as on a direct deal, closing today's gap where partner deals pay less.",
 "forecast": "Co-sell opportunities sit in the existing weekly forecast review with the same stage exit criteria as direct deals, flagged by the Partner Source field rather than tracked apart.",
 "kpis": [
  "Partner-sourced against partner-influenced revenue, quarter by quarter",
  "Activation rate: share of the three co-sell partners producing a lead or revenue",
  "Time to first deal per co-sell partner",
  "Partner CAC against direct CAC",
  "Share of the $1.04M blocked pipeline recovered"
 ],
 "caveats": [
  "The caps and the 14-day window are proposed; Sales leadership should confirm them before next quarter starts.",
  "The equal-comp change needs a budget, and the sponsor today has interest but none.",
  "Brieflyne AI and Slack are parked and get no attribution rule until demand evidence exists."
 ]
}

What step 5 prints for it: cosell: A co-sell deal carries one sourced partner per deal, chosen from Salesforce, DocuSign or HubSpot at creation, while any other of the three that advanced it is logged as influenced only.

The page's check: kept - nothing to flag

portfolio - A field-service platform with a program that holds

The page read it as: a partnership portfolio finance and partners can both trust; portfolio fewdeep, breadth, anchor; org alliances, sales, product; rungs QuickBooks cobuild, ServiceTitan Pay cosell, Google Calendar cosell, Angi Leads referral; 5 of 5 gates; failing checks: none.

Input (facts is 2163 characters; the first 1399 are shown):

{
 "task": "portfolio",
 "company": "Company: Coilwright\nThe product and what prompted this: A field-service management platform for HVAC and electrical contractors, re-evaluating a program that grew partner by partner.\nProgram today: A mature program being re-evaluated; demand data: A partner-source field on CRM opportunities; partnerships report to: A dedicated BD or Alliances org; executive sponsor: Yes, with budget; employees: 240\nThe business model supports partner-transacted deals: no; one platform dominates the customer base: no; partner-sourced revenue is a board metric: yes; productizing integrations is the goal: no\nAttribution today: CRM partner-source field yes; sourced and influenced reported separately; claimed at creation; caps set before the quarter yes; window 14 days; AE comp equal on partner deals yes; one forecast review yes\nHard deadline: no; a compounding asset; effort ceiling: high; as-of: 2026-11-01",
 "partners": "Candidate partners (partner | evidence | blocked deals | joint economics | proposed rung | the page's rung):\n- QuickBooks | evidence: 61% of accounts sync invoices; partner-sourced $1.2M pipeline in 4 quarters (numeric) | blocked deals $480k | joint economics proven | proposed co-build | page rung cobuild\n- ServiceTitan Pay | evidence: 27 deals in 2026 cited payments; retention 9 points higher with payments on (numeric) | blocked deals $220k | joint economics unproven | proposed co-sell | page rung cosell\n- Google Calendar | evidence: 1,100 accounts connected; 3 lost deals named scheduling (numeric) | joint economics unproven | proposed co-sell | page rung cosell\n- Angi Leads | evidence: 46 requests from CS in two quarters (numeric) | joint economics unproven | proposed referral | page rung referral\n\nCertification joins planned (platform | renewal owner | budget | cadence):\n- Intuit App Partner Program | renewal owner Integrations PM | 60 h a quarter | cadence annual\n- Google Workspace Marketplace verification | renewal owner Partner engineer | 24 h a quarter | cadence annual",
 "carry": "",
 "facts": "The page's checks (0 fail, 0 warn, 6 pass, 5 n/a); verdict: a partnership portfolio finance and partners can both trust:\n- Portfolio and depth | shortlist | na | 4 partners: 4 with numeric evidence, 0 with a source but no numbers, 0 with none\n- Portfolio and depth | shape | na | Few-and-deep > Category-coverage breadth > Platform-anchor\n- Portfolio and depth | evidence | pass | every partner names deals, requests, customers or retention\n- Portfolio and depth | graduation | pass | QuickBooks at co-build / strategic alliance - joint economics proven\n- Portfolio and depth | ladder | na | Co-build / strategic alliance > Co-sell / integration alliance > Referral > OEM / embed - the business model cannot support partner-transacted deals - the reseller rung is deleted, not parked; a compounding mandate with proven joint economics promotes co-build\n- Certifications | renewals | pass | Intuit App Partner Program - Integrations PM, 60 h a quarter; Google Workspace Marketplace verification - Partner engineer, 24 h a quarter\n- Attribution | attribution | pass | a CRM partner-source field, two capped numbers, claimed at creation\n- Attribution | window | pass | 14 days\n- Attribution | comp | pass | comp equalized and one forecast review\n- The function | org | na | A standalone Alliances org > Report into Sales > Integrations under Product - partner-sourced revenue is a board metric and deep\n\n[... 764 more characters cut from this display ...]"
}

Reply (long strings shortened for display - see the cuts below):

{
 "task": "portfolio",
 "summary": "Coilwright runs a few-and-deep portfolio led by a QuickBooks co-build, with ServiceTitan Pay and Google Calendar at co-sell and Angi Leads at referral; first, put QuickBooks under a joint business plan and quarterly QBRs.",
 "portfolio": {
  "shape": "fewdeep",
  "why": "Graduate QuickBooks to co-build on its proven joint economics, keep ServiceTitan Pay and Google Calendar as maintained co-sell integrations, hold Angi Leads at referral, and drop the reseller rung since partner-transacted deals do not fit [... 11 more characters cut from this display]"
 },
 "shortlist": [
  {
   "partner": "QuickBooks",
   "evidence": "61% of accounts sync invoices; partner-sourced $1.2M pipeline in 4 quarters; $480k in blocked deals",
   "rung": "cobuild",
   "next": "Moves toward OEM only if the co-build delivers its dated joint targets for consecutive quarters and both sides show product, commercial and operational fit for an embedded offer."
  },
  {
   "partner": "ServiceTitan Pay",
   "evidence": "27 deals in 2026 cited payments; retention 9 points higher with payments on; $220k in blocked deals",
   "rung": "cosell",
   "next": "Moves to co-build once co-sold payments deals, starting with the $220k blocked, show proven joint economics tracked through the partner-source field."
  },
  {
   "partner": "Google Calendar",
   "evidence": "1,100 accounts connected; 3 lost deals named scheduling",
   "rung": "cosell",
   "next": "Moves to co-build once the scheduling integration produces partner-sourced pipeline with joint economics proven against the 3 lost deals' profile."
  },
  {
   "partner": "Angi Leads",
   "evidence": "46 requests from CS in two quarters",
   "rung": "referral",
   "next": "Moves to co-sell once referrals turn into named, partner-sourced deals in the CRM rather than CS requests alone."
  }
 ],
 "governance": [
  {
   "partner": "QuickBooks",
   "cadence": "monthly sync, quarterly QBR (proposed)",
   "plan": "Shared dated targets of growing invoice-sync adoption past 61% of accounts and recovering the $480k blocked pipeline by 2027-06-30 (proposed), with Coilwright carrying the heavier engineering lift now.",
   "qbr": "Coilwright's Alliances lead and Integrations PM plus a QuickBooks partner leader who can commit resources review last quarter's commitments and set the next quarter's."
  }
 ],
 "certifications": [
  {
   "platform": "Intuit App Partner Program",
   "owner": "Integrations PM",
   "cost": "60 h a quarter",
   "cadence": "annual"
  },
  {
   "platform": "Google Workspace Marketplace verification",
   "owner": "Partner engineer",
   "cost": "24 h a quarter",
   "cadence": "annual"
  }
 ],
 "org": {
  "placement": "alliances",
  "why": "Partner-sourced revenue is a board metric and the QuickBooks co-build needs a dedicated owner, so the existing Alliances org with a budgeted sponsor keeps the function.",
  "roles": [
   "Partner managers",
   "Partner or integration engineer",
   "Integration product manager",
   "Top 10-15 partners run as named accounts"
  ]
 },
 "kpis": [
  "Partner-sourced against partner-influenced revenue on the board dashboard",
  "Activation rate across the four signed partners",
  "Time to first deal for ServiceTitan Pay, Google Calendar and Angi Leads",
  "Partner CAC against direct CAC",
  "QuickBooks joint-plan targets hit per quarter"
 ],
 "caveats": [
  "The QuickBooks joint business plan targets and dates are proposed; confirm them with QuickBooks at the first QBR."
 ]
}

Cut from this display only (the saved reply and the check use the full text): portfolio.why (249 characters, 238 shown).

What step 5 prints for it: QuickBooks: cobuild | ServiceTitan Pay: cosell | Google Calendar: cosell | Angi Leads: referral

The page's check: kept - nothing to flag

Build the input yourself

Load the engine in node (global.window = global; require("./pfkit.js"); require("./pfreply.js")), then:

const K = PartnerKit, R = PartnerReply;
const f = K.form(Object.assign(K.blank(), { name: "Acme", split: "blended", window: "14",
  partners: "HubSpot | 14 open deals blocked | $310k | no | co-sell\nZoomInfo | our CEO knows them | | no | co-build" }));
// f.partnerRows (each with kind, rec and why), f.shapeRank, f.ladderRank, f.orgRank (the ranked menus), f.gates
// K.scorecardCsv(f), K.rulesMd(f) - the scorecard and the attribution rules draft
const b = K.buildInput(f, "portfolio");                      // or "attribution" (R.laneForm(form, "attribution", portfolio) fills carry)
const wire = K.toWire(b.input);                              // POST this to /estimate and /run
// then: const reply = R.normalize(R.parseReply(job.output.output), "portfolio");
// R.check(reply, b)                                         // {status: kept or flagged, notes}

Get a token for the steps below from /tokens.html.

Step 1 — a tiny client helper

One function that sends JSON and unwraps the response. Paste a personal token from /tokens.html, or leave it empty and mint a guest token in step 2.

BASE="https://api.skillsafe.ai/v1/app-api"
TOKEN="YOUR_TOKEN"   # from https://partner-fit.skillsafe.ai/tokens.html
api() { # api METHOD PATH [JSON-BODY]
  curl -s -X "$1" "$BASE$2" -H "Content-Type: application/json" \
    ${TOKEN:+-H "Authorization: Bearer $TOKEN"} ${3:+--data "$3"}
}

Step 2 — a token

A guest token is enough for /me and /estimate. A run is metered, so it needs a personal token: sign in on /tokens.html and copy it from there.

# a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN=$(curl -s -X POST "$BASE/guest" -H "Content-Type: application/json" -d '{"slug":"partner-fit"}' | jq -r '.data.token')

Step 3 — GET /me

Who the token is (subject_type: user or guest) and the credit balance.

api GET /me | jq '.data | {subject_type, credits}' 

Step 4 — POST /estimate

Free. The body is the run input itself, the bare object (never wrapped in {"input": ...}). hold_credits is a reservation, not the price; min_credits is what the balance must cover; model_alias reads gpt-terra.

# input.json: the run input object - {"task": "portfolio", "company": "Company: Clausewick
The product and what prompted this: ...", "partners": "Candidate partners (partner | evidence | ...):
- Salesforce | evidence: 38% of customers run it ...", "carry": "", "facts": "The page's checks (...); verdict: partners picked on relationships - evidence first:
- Portfolio and depth | evidence | fail | ..."}
# - see the input table
api POST /estimate "$(cat input.json)" | jq '.data | {hold_credits, min_credits, model, model_alias, markup_bps, warnings}' 

Step 5 — POST /run, then poll the job

Send an Idempotency-Key built from the lane and the input: a retry with the same key never bills twice. The page uses partner-fit:<task>:<inputHash>:a<attempt> - the lane is part of the key, retry_note is left out of the hash - and its one automatic reformat retry is a new attempt number, named in the page as one extra run. A portfolio reply carries summary, portfolio, shortlist, governance, certifications, org, kpis and caveats; an attribution reply carries summary, definitions, claim, caps, motions, comp, forecast, kpis and caveats. The code below prints the gist of either: each partner and its rung, or each motion and its rule.

KEY="partner-fit:$(jq -r .task input.json):$(shasum -a 256 input.json | cut -c1-16):a1"
JOB=$(curl -s -X POST "$BASE/run" -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: $KEY" --data @input.json | jq -r '.data.job_id')
while :; do
  J=$(api GET "/jobs/$JOB"); S=$(echo "$J" | jq -r '.data.status')
  case "$S" in succeeded|failed|cancelled) break;; esac; sleep 2
done
echo "$J" | jq -r '.data.output.output' > reply.json   # one JSON object, the reply contract
echo "$J" | jq '.data | {charged_credits, truncated}'
jq -r 'if .task == "attribution" then (.motions[] | "\(.rung): \(.rule)") 
       else (.shortlist[] | "\(.partner): \(.rung)") end' reply.json

Step 6 — POST /run-stream

The same run as Server-Sent Events, with the same input.json. Browsers receive progress ticks rather than text deltas; the final done event carries the reply.

# Server-Sent Events: tick/delta events while the job runs, then a final event with the job
curl -N -s -X POST "$BASE/run-stream" -H "Content-Type: application/json" -H "Authorization: Bearer $TOKEN" \
  -H "Idempotency-Key: partner-fit:$(jq -r .task input.json):$(shasum -a 256 input.json | cut -c1-16):a1" --data @input.json