← Signed or Stalled / API
Tokens

Drive Signed or Stalled from your own code

The page does its free work in the browser: it reads the deal box (deal size, average ACV, close date, stage, first meeting, MAP last updated, POC, EB approved, competition), the stakeholder list, the mutual action plan (CSV, TSV or a Markdown table) and your call notes, and works out MAP health by the 3-week rule, which side owns each action, what is overdue, the stage the exit criteria support, full or simplified plan, the proposal decision and flags MD-01..MD-14. Its two paid lanes are available over HTTP. You send one JSON object with task set to "qualify" or "plan", and the model replies with one JSON object. The easiest way to build the facts string is the page itself: DealKit.buildInput(lane, DealKit.analyze(deal, people, map, notes, {account, question, today}), {handoff}) in dealkit.js, which also runs under Node.

Base URL: https://api.skillsafe.ai/v1/app-api. Every call sends Content-Type: application/json and, once you have a token, Authorization: Bearer <token>. Both lanes run on gpt-terra with a 10% publisher markup. A run needs a signed-in (user) token and is metered: the platform holds the estimate's hold_credits while the run is in flight and then charges only what it used (charged_credits). /estimate is free. A plain-text summary is at /llms.txt.

The response envelope

Every response is {"data": ..., "error": null} on success or {"data": null, "error": {"code", "message"}} on failure.

Error codes

HTTPcodemeaning
400VALIDATION_ERRORThe body is not a JSON object, or a field is the wrong type. Every field of the run input is a string.
401UNAUTHORIZEDNo token, or an expired one: get a new one (step 2).
402INSUFFICIENT_CREDITSThe balance is below the run's minimum. Top up at skillsafe.ai/account/billing/.
403FORBIDDENA guest token tried a metered run: sign in for a personal token.
404NOT_FOUNDUnknown job id.
429RATE_LIMITEDBack off and retry with the same Idempotency-Key.

The task field: two lanes

taskwhat the model does
"qualify"Is the deal alive: a verdict (advance, hold, reset, qualify out) bound by the MAP health, the stage the criteria support, the seven MEDDICC elements graded validated, assumed or missing with quotes, the six-item economic-buyer checklist and send_proposal, each stakeholder's personal win, risk and pitch, risks and next steps.
"plan"The mutual action plan rebuilt: 5-15 rows with your owner and a named customer owner on at least 40% of them, every open action carried or dropped, the EB met before pricing, the eb_ask, the weekly cadence and the week-1/2/3 silence_ladder.

Input fields (all strings)

fieldwhencontent
taskrequiredqualify or plan
accountoptionalThe account's name.
todayrequiredThe as-of date, YYYY-MM-DD: staleness, overdue actions and the dates of the plan are counted from it.
dealrequiredThe deal box as pasted ("Key: value" lines). Past 3,000 characters the page cuts the middle and says so.
peoplerequiredThe stakeholder list as pasted: name | title | role | met or not met | notes.
notesrequiredThe call notes, numbered N1: ... by the page; past 9,000 characters the middle lines are dropped with a marker.
factsrequiredA JSON string: today, account, deal{size, average_acv, close_date, stage_claimed, first_meeting, competition[], poc, eb_approved}, map{health, reasons[], last_updated, days_since_update, counts}, days_to_close, gates{claimed, supported, failed[]}, plan_type{type, cycle_days, why}, proposal, eb{named, ids[], met}, champion{named, ids[]}, stakeholders[{id, name, title, role, met, notes}], actions[{id, action, our_owner, customer_owner, others, due, status, overdue, updated}] (up to 40), meddicc_mentions, flags[], notes[].
questionoptionalWhat you want to know; answered in summary.
qualify_handoffplan, optionalA JSON string of the qualify verdict the plan follows: verdict, map_health, send_proposal, gaps[{element, status, next_question}], risks[], next_steps[].
retry_noteoptionalOnly on a reformat retry: what was wrong with the previous reply.

The reply contracts

Both lanes share an envelope: task, task_note, headline, questions[], summary.

task: "qualify"

verdict, map_health (exactly the page's), stage_claimed, stage_supported, stage_note, plan_type, meddicc[{element, status: validated|assumed|missing, evidence[], source_ids[], gap, next_question}] (exactly 7, in order), eb_checklist[{item, answer: yes|no|unknown, evidence}] (exactly 6, in order), send_proposal: yes|no, stakeholders[{id, personal_win, professional_risk, motivation, pitch}], risks[{risk, severity: high|medium|low, mitigation, owner}] (1-6), next_steps[{step, owner, by}] (2-6).

task: "plan"

source (qualify handoff|from the input), close_date, actions[{action, our_owner, customer_owner, stakeholder_id, others, due, status: complete|in progress|not started, from: A-id|new, why}] (5-15, sorted by due), dropped[{id, why}], cadence, eb_ask, silence_ladder{week_1, week_2, week_3}.

Worked examples

These are the page's own bundled examples (invented companies, people and numbers), with the input as app.js builds it and the saved model reply the page replays for free: one qualification of a dying deal and its plan after the handoff, one qualification of a healthy deal, and one plan from a seller-only MAP.

Qualify: a $240K deal with a red MAP and an economic buyer nobody has met

Input (each pasted text shown as its lines; facts shortened here):

{
 "task": "qualify",
 "account": "Northwindle Logistics",
 "today": "2026-10-01",
 "deal": [
  "Product: Beaconly incident-response platform (on-call, alerting, status pages)",
  "Deal size: $240,000 a year",
  "Average ACV: $60,000",
  "Stage: 4 Proposal",
  "First meeting: 2026-06-30",
  "Close date: 2026-10-31",
  "... (11 lines in all)"
 ],
 "people": [
  "Dana Ruizvald | VP Engineering | champion | met | 6 months in role, needs a visible uptime win before the board review in December; her last monitoring pick was dropped",
  "Marcus Feldqvarn | CFO | economic buyer | not met | signs anything over $100K; Dana says he is \"traveling\" and she will \"handle him\"",
  "Priya Natteram | Staff SRE | technical evaluator | met | ran the pilot; wants fewer 3am pages for her team",
  "Tom Akervik | Director of IT Procurement | procurement | not met",
  "Lena Ortavane | Platform Engineering Lead | blocker | met | built the in-house Grafana OnCall setup and prefers to extend it",
  ""
 ],
 "notes": [
  "N1: 2026-06-30 Discovery call with Dana: on-call burnout is the problem - two SREs quit this year and both named the pager in exit interviews.",
  "N2: 2026-06-30 Dana: \"We had four sev-1 outages last quarter and it took us 40 minutes on average just to get the right person on the call.\"",
  "N3: 2026-07-14 Demo to Dana, Priya and Lena. Lena asked why they would not just extend their Grafana OnCall setup.",
  "N4: 2026-07-22 Dana agreed to a two-week pilot; success criteria: cut pages for the pilot team by 30% and get time-to-acknowledge under 5 minutes.",
  "N5: 2026-08-21 Pilot readout: pages down 38%, time-to-acknowledge 4 minutes. Priya is a fan.",
  "N6: 2026-08-28 Dana: \"I can sell this internally, leave Marcus to me.\"",
  "... (10 lines in all)"
 ],
 "facts": "(a JSON string; decoded: deal size 240000, average ACV 60000, close 2026-10-31, stage claimed 4 / supported 4, MAP red (last updated 26 days ago (over 3 weeks); 2 customer actions are overdue), 5 stakeholders, 7 actions, EB named True / met False, plan type full, proposal no; flags MD-02, MD-05, MD-08, MD-13)",
 "question": "Is this deal still alive, and should I go around Dana to the CFO?"
}

Reply:

{
 "task": "qualify",
 "task_note": "",
 "verdict": "reset",
 "map_health": "red",
 "stage_claimed": 4,
 "stage_supported": 4,
 "stage_note": "The pilot met its success criteria, so entry to stage 4 holds, but the stage 4 exit is not in reach: the proposal went to Dana, not to an aligned economic buyer.",
 "plan_type": "full",
 "meddicc": [
  {
   "element": "metrics",
   "status": "assumed",
   "evidence": [
    "success criteria: cut pages for the pilot team by 30% and get time-to-acknowledge under 5 minutes",
    "Pilot readout: pages down 38%, time-to-acknowledge 4 minutes."
   ],
   "source_ids": [
    "N4",
    "N5"
   ],
   "gap": "The pilot metrics were agreed with Dana and the SRE team; Marcus Feldqvarn has not confirmed which business outcome justifies $240K a year.",
   "next_question": "Ask Marcus Feldqvarn, in a meeting Dana sets up: what result would make this spend worth it to you, and how would you measure it?"
  },
  {
   "element": "economic buyer",
   "status": "assumed",
   "evidence": [
    "signs anything over $100K; Dana says he is \"traveling\" and she will \"handle him\"",
    "Emailed Dana for the CFO review date - no reply."
   ],
   "source_ids": [
    "S2",
    "N9"
   ],
   "gap": "Marcus Feldqvarn is named but has never been met, and we do not know whether he has seen the proposal.",
   "next_question": "Ask Dana Ruizvald: can you get us 15 minutes with Marcus this month to align on outcomes and timeline before he reviews pricing?"
  },
  {
   "element": "decision criteria",
   "status": "assumed",
   "evidence": [
    "success criteria: cut pages for the pilot team by 30% and get time-to-acknowledge under 5 minutes",
    "Lena asked why they would not just extend their Grafana OnCall setup."
   ],
   "source_ids": [
    "N4",
    "N3"
   ],
   "gap": "Technical criteria came from the pilot; the business and political criteria (build versus buy, existing vendor agreements) are not confirmed.",
   "next_question": "Ask Dana Ruizvald: beyond the pilot results, what will Marcus and procurement weigh when choosing between us, PagerDuty and extending Grafana OnCall?"
  },
  {
   "element": "decision process",
   "status": "assumed",
   "evidence": [
    "Dana said they are also looking at PagerDuty because procurement has a master agreement with them.",
    "signs anything over $100K"
   ],
   "source_ids": [
    "N8",
    "S2"
   ],
   "gap": "We know th
... (shortened here; the page shows it whole)

Plan: the same deal, with the qualify verdict handed over

Input (with the qualify verdict handed over; texts shown as lines):

{
 "task": "plan",
 "account": "Northwindle Logistics",
 "today": "2026-10-01",
 "deal": [
  "Product: Beaconly incident-response platform (on-call, alerting, status pages)",
  "Deal size: $240,000 a year",
  "Average ACV: $60,000",
  "Stage: 4 Proposal",
  "First meeting: 2026-06-30",
  "Close date: 2026-10-31",
  "... (11 lines in all)"
 ],
 "people": [
  "Dana Ruizvald | VP Engineering | champion | met | 6 months in role, needs a visible uptime win before the board review in December; her last monitoring pick was dropped",
  "Marcus Feldqvarn | CFO | economic buyer | not met | signs anything over $100K; Dana says he is \"traveling\" and she will \"handle him\"",
  "Priya Natteram | Staff SRE | technical evaluator | met | ran the pilot; wants fewer 3am pages for her team",
  "Tom Akervik | Director of IT Procurement | procurement | not met",
  "Lena Ortavane | Platform Engineering Lead | blocker | met | built the in-house Grafana OnCall setup and prefers to extend it",
  ""
 ],
 "notes": [
  "N1: 2026-06-30 Discovery call with Dana: on-call burnout is the problem - two SREs quit this year and both named the pager in exit interviews.",
  "N2: 2026-06-30 Dana: \"We had four sev-1 outages last quarter and it took us 40 minutes on average just to get the right person on the call.\"",
  "N3: 2026-07-14 Demo to Dana, Priya and Lena. Lena asked why they would not just extend their Grafana OnCall setup.",
  "N4: 2026-07-22 Dana agreed to a two-week pilot; success criteria: cut pages for the pilot team by 30% and get time-to-acknowledge under 5 minutes.",
  "N5: 2026-08-21 Pilot readout: pages down 38%, time-to-acknowledge 4 minutes. Priya is a fan.",
  "N6: 2026-08-28 Dana: \"I can sell this internally, leave Marcus to me.\"",
  "... (10 lines in all)"
 ],
 "facts": "(a JSON string; decoded: deal size 240000, average ACV 60000, close 2026-10-31, stage claimed 4 / supported 4, MAP red (last updated 26 days ago (over 3 weeks); 2 customer actions are overdue), 5 stakeholders, 7 actions, EB named True / met False, plan type full, proposal no; flags MD-02, MD-05, MD-08, MD-13)",
 "question": "Is this deal still alive, and should I go around Dana to the CFO?",
 "qualify_handoff": "{\"verdict\":\"reset\",\"map_health\":\"red\",\"send_proposal\":\"no\",\"gaps\":[{\"element\":\"metrics\",\"status\":\"assumed\",\"next_question\":\"Ask Marcus Feldqvarn, in a meeting Dana sets up: what result would make this spend worth it to you, and how would you measure it?\"},{\"element\":\"economic buyer\",\"status\":\"assumed\",\"next_question\":\"Ask D..."
}

Reply:

{
 "task": "plan",
 "task_note": "",
 "source": "qualify handoff",
 "close_date": "2026-10-31",
 "actions": [
  {
   "action": "Pilot with the SRE team",
   "our_owner": "Sam (SE)",
   "customer_owner": "Priya Natteram",
   "stakeholder_id": "S3",
   "others": "",
   "due": "2026-08-21",
   "status": "complete",
   "from": "A1",
   "why": "Done: pages down 38% and time-to-acknowledge 4 minutes against the agreed criteria."
  },
  {
   "action": "Pilot readout to Dana",
   "our_owner": "Sam (SE)",
   "customer_owner": "Dana Ruizvald",
   "stakeholder_id": "S1",
   "others": "",
   "due": "2026-08-28",
   "status": "complete",
   "from": "A2",
   "why": "Done: the champion has the pilot results to sell internally."
  },
  {
   "action": "Send proposal and order form",
   "our_owner": "Jordan (AE)",
   "customer_owner": "",
   "stakeholder_id": "",
   "others": "",
   "due": "2026-09-05",
   "status": "complete",
   "from": "A3",
   "why": "Done, but sent before the economic buyer was met; the price is with Marcus Feldqvarn without his agreement on problem, metrics or timeline."
  },
  {
   "action": "Reset call with Dana now she is back: confirm the date she is working to, what has happened with Marcus since the proposal, and agree this MAP",
   "our_owner": "Jordan (AE)",
   "customer_owner": "Dana Ruizvald",
   "stakeholder_id": "S1",
   "others": "",
   "due": "2026-10-01",
   "status": "not started",
   "from": "new",
   "why": "The MAP is 26 days stale; by the 3-week rule it must be reset now. Closes the champion gap: is Dana actively selling, and what does she need before the board review in December?"
  },
  {
   "action": "Map the path to signature with procurement: security review, MSA redlines, CFO approval, how long each takes, and how the PagerDuty master agreement affects this purchase",
   "our_owner": "Sam (SE)",
   "customer_owner": "Tom Akervik",
   "stakeholder_id": "S4",
   "others": "Dana Ruizvald",
   "due": "2026-10-06",
   "status": "not started",
   "from": "new",
   "why": "Closes the decision process gap; Tom Akervik has not been met and procurement already has a master agreement with PagerDuty."
  },
  {
   "action": "15 minutes with Marcus Feldqvarn to align on the problem, how he will measure success, and the timeline before he reviews pricing",
   "our_owner": "Jordan (AE)",
   "customer_owner": "Marcus Feldqvarn",
   "stakeholder_id": "S2",
   "others": "Dana
... (shortened here; the page shows it whole)

Qualify: a green MAP in paper process, EB met and approved

Input (texts shown as lines):

{
 "task": "qualify",
 "account": "Harborvane Partners",
 "today": "2026-10-01",
 "deal": [
  "Product: Tallymark spend-management platform",
  "Deal size: $95,000 ARR",
  "Average ACV: $40,000",
  "Stage: 5 Paper process",
  "First meeting: 2026-07-08",
  "Close date: 2026-10-24",
  "... (11 lines in all)"
 ],
 "people": [
  "Grace Hollowmere | CFO | economic buyer | met | wants month-end close cut from 9 days to 5 before the audit; measured on close speed this year",
  "Owen Parwick | Controller | champion | met | runs the close and owns the spreadsheets; up for promotion to VP Finance",
  "Ines Barrovel | IT Director | security | met | burned by a vendor breach in 2024, insists on SOC 2 Type II",
  "Felix Granholt | General Counsel | legal | not met | reviewing the MSA",
  "Ruth Adeyemvo | AP Manager | user | met | wants approvals out of email",
  ""
 ],
 "notes": [
  "N1: 2026-07-08 First call with Owen: month-end close takes 9 days, mostly chasing receipts and approvals in email.",
  "N2: 2026-07-21 Grace joined the demo: success metric is close in 5 days by the March audit, and fewer late vendor payments.",
  "N3: 2026-08-04 Owen shared their evaluation criteria: card controls, NetSuite sync, SOC 2 Type II, approval routing.",
  "N4: 2026-08-19 They are also evaluating Spendlark; Owen says our NetSuite sync won the bake-off.",
  "N5: 2026-09-22 Grace approved the business case and the budget; procurement path is security review, then legal, then signature.",
  "N6: 2026-09-28 Ines signed off on security. Felix has the MSA and promised redlines by October 7.",
  "... (7 lines in all)"
 ],
 "facts": "(a JSON string; decoded: deal size 95000, average ACV 40000, close 2026-10-24, stage claimed 5 / supported 5, MAP green (updated within a week, both sides own actions, no customer action overdue), 5 stakeholders, 6 actions, EB named True / met True, plan type full, proposal depends; flags none)"
}

Reply:

{
 "task": "qualify",
 "task_note": "",
 "verdict": "advance",
 "map_health": "green",
 "stage_claimed": 5,
 "stage_supported": 5,
 "stage_note": "Stage 5 is supported: Grace Hollowmere approved the business case and budget on 2026-09-22 and security signed off on 2026-09-28; the exit criterion for stage 5, approvals secured, now depends on legal redlines from Felix Granholt and the order form signature.",
 "plan_type": "full",
 "meddicc": [
  {
   "element": "metrics",
   "status": "validated",
   "evidence": [
    "Grace joined the demo: success metric is close in 5 days by the March audit, and fewer late vendor payments."
   ],
   "source_ids": [
    "N2",
    "S1"
   ],
   "gap": "No baseline or target for late vendor payments.",
   "next_question": "Ask Grace Hollowmere: how do you count late vendor payments today, and what number would you call a win by the March audit?"
  },
  {
   "element": "economic buyer",
   "status": "validated",
   "evidence": [
    "Grace approved the business case and the budget; procurement path is security review, then legal, then signature."
   ],
   "source_ids": [
    "N5",
    "S1"
   ],
   "gap": "",
   "next_question": ""
  },
  {
   "element": "decision criteria",
   "status": "validated",
   "evidence": [
    "Owen shared their evaluation criteria: card controls, NetSuite sync, SOC 2 Type II, approval routing."
   ],
   "source_ids": [
    "N3",
    "S2"
   ],
   "gap": "Political criteria are not written down; we only have the technical and business list from Owen Parwick.",
   "next_question": "Ask Owen Parwick: is there anyone beyond Grace Hollowmere who could still question the choice of Tallymark before signature?"
  },
  {
   "element": "decision process",
   "status": "validated",
   "evidence": [
    "procurement path is security review, then legal, then signature.",
    "Ines signed off on security. Felix has the MSA and promised redlines by October 7."
   ],
   "source_ids": [
    "N5",
    "N6"
   ],
   "gap": "Unknown whether a purchase order or vendor setup step sits between legal and signature, and who countersigns the order form.",
   "next_question": "Ask Owen Parwick: after Felix Granholt returns the redlines, what happens between legal approval and Grace Hollowmere signing - is a PO or vendor setup needed?"
  },
  {
   "element": "identified pain",
   "status": "validated",
   "evidence": [
    "First call with Owen: mon
... (shortened here; the page shows it whole)

Plan: a POC-stage MAP where only the seller owns actions

Input (texts shown as lines):

{
 "task": "plan",
 "account": "Quarrybrook Health",
 "today": "2026-10-01",
 "deal": [
  "Product: Fieldglass Analytics - a data quality platform",
  "Deal size: $150,000",
  "Average ACV: $70,000",
  "Stage: Proving value",
  "First meeting: 2026-08-11",
  "Close date: 2026-12-15",
  "... (9 lines in all)"
 ],
 "people": [
  "Hannah Colverde | Head of Data Platform | champion | met | wants to stop being paged for broken dashboards; new in role",
  "Victor Lundkvarn | VP Data | economic buyer | not met | owns the data budget",
  "Arjun Mehtavar | Analytics Engineer | technical evaluator | met | running the POC",
  "Sofia Brandvik | Procurement Manager | procurement | not met",
  ""
 ],
 "notes": [
  "N1: 2026-08-11 Hannah: broken dashboards reach the exec team before her team knows; last month a revenue dashboard was wrong for three days.",
  "N2: 2026-08-25 Demo went well. Hannah wants a POC on their Snowflake sandbox.",
  "N3: 2026-09-10 Arjun connected the sandbox. No success criteria agreed yet; Hannah said \"we will know it when we see it\".",
  "N4: 2026-09-24 Hannah mentioned Victor has to approve anything over $100K and that they looked at Monte Carlo last year."
 ],
 "facts": "(a JSON string; decoded: deal size 150000, average ACV 70000, close 2026-12-15, stage claimed 3 / supported 3, MAP red (no action has a customer owner; the last update date is unknown), 4 stakeholders, 4 actions, EB named True / met False, plan type full, proposal no; flags MD-04, MD-08, MD-12, MD-13)",
 "question": "What should the MAP look like before I send pricing?"
}

Reply:

{
 "task": "plan",
 "task_note": "",
 "source": "from the input",
 "close_date": "2026-12-15",
 "actions": [
  {
   "action": "Connect to the Snowflake sandbox",
   "our_owner": "Ben (SE)",
   "customer_owner": "Arjun Mehtavar",
   "stakeholder_id": "S3",
   "others": "",
   "due": "2026-09-25",
   "status": "complete",
   "from": "A1",
   "why": "Done; Arjun connected the sandbox (N3). Kept as a record, not re-dated."
  },
  {
   "action": "Write down the POC success criteria: which broken-dashboard incidents the platform must catch, and how fast",
   "our_owner": "Kate (AE)",
   "customer_owner": "Hannah Colverde",
   "stakeholder_id": "S1",
   "others": "Arjun Mehtavar, Ben (SE)",
   "due": "2026-10-06",
   "status": "not started",
   "from": "new",
   "why": "No success criteria agreed yet (N3); stage 3 cannot exit without them, and \"we will know it when we see it\" is not a criterion."
  },
  {
   "action": "Build the first ten data-quality monitors on the dashboards Hannah's team named",
   "our_owner": "Ben (SE)",
   "customer_owner": "Arjun Mehtavar",
   "stakeholder_id": "S3",
   "others": "",
   "due": "2026-10-06",
   "status": "in progress",
   "from": "A2",
   "why": "Arjun is running the POC; he picks the tables and confirms each monitor works."
  },
  {
   "action": "Weekly MAP check-in: walk the MAP row by row, update owners, dates and status",
   "our_owner": "Kate (AE)",
   "customer_owner": "Hannah Colverde",
   "stakeholder_id": "S1",
   "others": "Arjun Mehtavar, Ben (SE)",
   "due": "2026-10-08",
   "status": "not started",
   "from": "A3",
   "why": "Turns the POC check-in into the running agenda of the deal so the customer owns and updates actions every week."
  },
  {
   "action": "15-minute call with Victor Lundkvarn to align on the outcome (broken dashboards reaching the exec team), the success metrics and the timeline to 2026-12-15",
   "our_owner": "Kate (AE)",
   "customer_owner": "Victor Lundkvarn",
   "stakeholder_id": "S2",
   "others": "Hannah Colverde",
   "due": "2026-10-13",
   "status": "not started",
   "from": "new",
   "why": "Victor is the economic buyer and has not been met; he has to approve anything over $100K (N4) and this deal is $150,000. No pricing before this meeting."
  },
  {
   "action": "Map the decision process: procurement steps, legal and security review, vendor onboarding and who signs",
   "our_owner": "Kate (AE)",
   "customer_owne
... (shortened here; the page shows it whole)

The page re-checks the reply; the API does not

The page holds every reply to account (recon.js). For a qualification: the MAP health, claimed stage and plan type are the page's own; the supported stage is no higher than the exit criteria allow; a red MAP allows only reset or qualify out and only a green one allows advance; the seven MEDDICC elements come in order, a validated one is quoted, the economic buyer and metrics are validated only if the EB was met and the champion only if one is named; the six EB-checklist items come in order with identified and met as the stakeholder list says and any other yes quoted; the proposal goes out only on six yeses; every economic buyer and champion is mapped; next steps are dated from today to the close. For a plan: the close date is the deal's; 5 to 15 rows sorted by due date; every open action of the MAP is carried or dropped with a reason and completed ones are never reopened; at least 40% of the rows (and 2) are owned by a named stakeholder; open rows are due from today and not after the close unless post-signature; when the EB has not been met, a row with the EB comes before any pricing row and an ask for the champion is written; a weekly check-in; all three silence messages. In both, quotes are checked word for word and no figure the input, the page's reading or the skill does not contain may appear. Over the API you get the model's reply as it is; run the same checks yourself with Recon.reconcile in recon.js, or paste the same input into the page.

Step 1 — a tiny client helper

One function that sends JSON and unwraps the envelope.

BASE="https://api.skillsafe.ai/v1/app-api"
TOKEN="paste-your-token-here"   # from https://signed-or-stalled.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":"signed-or-stalled"}' | 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 (not wrapped in {"input": ...}). hold_credits is a reservation, not the price; min_credits is what the balance must cover; model reads gpt-5.6-terra and model_alias gpt-terra.

# input.json: the run input object - {"task": "qualify", "account": "...", "today": "...", "deal": "...", "people": "...", "notes": "...", "facts": "..."}
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 signed-or-stalled:<lane>:<inputHash>:a<attempt>. The job's output.output is the reply text; truncated: true means the balance cut it short.

KEY="signed-or-stalled:qualify:$(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 lane's contract
echo "$J" | jq '.data | {charged_credits, truncated}' 

Step 6 — POST /run-stream (plan)

The same run as Server-Sent Events. plan.json is a plan-lane input, with qualify_handoff when it follows a qualify verdict.

# 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: signed-or-stalled:plan:$(shasum -a 256 plan.json | cut -c1-16):a1" --data @plan.json