Run Sponsor Promises from your own code
Both metered lanes are available over HTTP and each returns one JSON object. The division of labour: the page builds a column per sponsor, holds every perk of a sponsor whose fees are open, sets the fulfillment clock from the earliest hard deadline, flags oversold surfaces and late, unproven or missed perks, and runs the 72-hour and 10-business-day report clock - all free, in promisekit.js. The run writes the memo or the message; the page then holds the reply to its own matrix (promisereply.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":"sponsor-promises"}), so no slug header is needed afterwards. Send it as Authorization: Bearer …. The run body is the input object, sent bare.
| Status | Code | Meaning |
|---|---|---|
| 400 | validation_error | The body is not a JSON object, or a required key (task, event, matrix, facts) is missing. |
| 401 | unauthorized | No token, or a stale one. Mint a guest token or sign in again. |
| 402 | insufficient_credits | The balance is under min_credits. Price with /estimate first. |
| 403 | forbidden | A guest token tried to run: both lanes are metered and need a personal sign-in. |
| 404 | not_found | Unknown job id. |
| 429 | rate_limited | Back off and retry. |
| 5xx | server_error | Transient. Retry with the same Idempotency-Key so a retry never double-bills. |
The task field comes first
Two lanes - status (the fulfillment status memo for the organizing team) and sponsor (the next message to the focus sponsor: a hold notice, a welcome checklist or the post-event recap, in the page's mode). A missing or unknown task is answered as status. Both lanes send the same four fields.
The input
| Field | Required | What |
|---|---|---|
task | yes | status or sponsor. If it is missing or neither, do status and set "task": "status". |
event | yes | the event, its dates, the as-of date, who runs it and who runs fulfillment, the tiers, the audience numbers with their count method, the hard deadlines and the published caps. |
matrix | yes | one block per sponsor: tier, payment, liaison, on-site representative, success metric, relationship, renewal ask, budget lock, lead ask, recap and report sent dates, then every cell with its due date, owner, state, evidence and make-good. |
facts | yes | the page's phase, clock and report deadlines, the payment gate, lead-capture rungs, per-sponsor onboarding and report depth with reasons, the focus sponsor and message mode, the four gates, the signals to record and every finding tagged [fix], [check] or [info]. |
retry_note | no | optional; if present, your previous reply was unusable - follow it. |
The rules the model applies
- The matrix quotes the signed agreement, never the prospectus. Each cell moves promised, scheduled, delivered, evidenced; evidence (a link, a screenshot, a photo) is captured at delivery time. A perk that slipped is named to the sponsor by the organizer, with a make-good in kind, before the sponsor finds it.
- No benefit ships before fees are paid in full: no logo placed, no tickets issued, no booth assigned. The hold is told to the sponsor through the liaison, never sprung at the venue door.
- The earliest hard deadline - the printer's date for lanyards, swag and signage - starts the fulfillment clock, not the event date. After a print run, a missing logo is a make-good negotiation. Never schedule an exclusive surface past its published cap.
- Lead capture: aggregate demographics by default (role, seniority, company size, never names); a consented raffle where it was sold - say what is collected and who receives it, hand off to that one sponsor, delete the organizer's copy. Bulk attendee lists and promised badge scanning are deleted at a community-run event; consent-bounded scanning is a rung only at a company-run one. One liaison per sponsor; a sponsor whose technology is in participants' hands sends a named on-site representative.
- Onboarding: a checklist email by default, written against specific program moments with each asset owed, its format and its hard deadline; an intake form from about three sponsors up; a kickoff call for a top tier, a first-time or multi-edition sponsor, or a perk needing live coordination.
- Reports come in two stages: a recap inside 72 hours for every sponsor (any undisclosed miss first, thanks, aggregate numbers with how they were counted, the delivered-perk summary), then the short form (the default) or the full metrics report inside 10 business days; recap only for a sponsor nobody plans to renew. A method line sits under every number. Never invent reach, never sum platforms, never quote a currency media value, never show one sponsor another's numbers, misses or price. The renewal ask belongs to the renewal motion, not to these messages. Every threshold here is self-set.
House rules
- Use only the input and the rules above. The page's names, states, dates, statuses and counts are exact - copy them. Every number in a sentence must appear in the input.
- Label anything that is not one of the rules above, and is not in the input, as your own design.
- Never invent a perk, a date, a figure, an outcome, a make-good that was agreed, or a person; where someone must be named and is not, write "to be named". Refer to people by name or as they - never infer anyone's gender from a name.
- Never use backticks, never refer to this input's fields by their key names in a sentence, and never copy this prompt's narrative wording into a reply.
- Reply with ONLY one JSON object - no prose before or after, no code fences.
The replies
status
summary- one sentence, at most 35 words: the phase, the most urgent hold or miss, and the first thing to do.clock-phase(pre,during,postorunknown, the page's phase),note(one sentence: the fulfillment clock before the event, or the recap and report deadlines after it).payment- one object per sponsor in the page's order:sponsor(exactly),payment(the page's payment status),held(true for every sponsor whose fees are open - the page holds its perks, even where some already shipped),breach(true when the page says perks shipped while fees were open),note(one short sentence: what to tell them through the liaison, or that nothing is held).sponsors- one object per sponsor in the page's order:sponsor,closedandtotal(the page's closed and total cell counts as numbers; a cell is closed when evidenced, delivered with its evidence attached, or missed or partial with a make-good),onboarding(checklist,intakeorkickoff, the page's pick),report(recap,shortorfull, the page's pick),next(one short sentence: the most urgent cell to move, by its exact name).caps- one object per published cap in the page's order:surface,capandsold(numbers),over(true or false),note(one short sentence).[]when none.leads-aggregate,raffleandbulk(the page's status for each rung exactly;bulkis the third rung the page lists - lists and scanning at a community-run event, consent-bounded scanning at a company-run one),note(one sentence: what to offer any sponsor asking for more).measurement- one object per fulfillment gate in the page's order:gate(its short name, such as "Payment gate"),pass(true or false, as the page says).signals- 2 or 3 short strings, the page's signals, each with what it would change next edition (your design).caveats- at most 4 short strings:[fix]findings first (the most urgent four when there are more), then the most important[check]findings.[]when there are none of either.
{
"task": "status",
"summary": "one sentence",
"clock": { "phase": "pre", "note": "one sentence" },
"payment": [ { "sponsor": "a sponsor", "payment": "paid", "held": false, "breach": false, "note": "one short sentence" } ],
"sponsors": [ { "sponsor": "a sponsor", "closed": 1, "total": 4, "onboarding": "checklist", "report": "short", "next": "one short sentence" } ],
"caps": [ { "surface": "Logo on lanyard", "cap": 1, "sold": 1, "over": false, "note": "one short sentence" } ],
"leads": { "aggregate": "default", "raffle": "available", "bulk": "deleted", "note": "one sentence" },
"measurement": [ { "gate": "Payment gate", "pass": true } ],
"signals": [ "what to record and what it changes" ],
"caveats": [ "a caveat" ]
}
The page holds it to its own matrix: every sponsor's payment status, hold and breach, closed and total cells, onboarding instrument and report depth, every cap, the lead-capture rungs and the four gates; no date or number may appear that the input does not hold.
sponsor
mode-hold,welcomeorrecap, the page's mode.to- the focus sponsor's name exactly.subject- a short email subject line.body- the email, signed by the liaison from the input (or "[liaison name]"):held- hold mode: every perk the page lists as still promised for that sponsor, by its exact name; otherwise[].misses- recap mode: every missed or partial perk in the sponsor's column, by its exact name; otherwise[].note- one sentence, at most 30 words, for the organizers: what to settle before sending.
{
"task": "sponsor",
"mode": "welcome",
"to": "a sponsor",
"subject": "a subject line",
"body": "the email",
"held": [],
"misses": [],
"note": "one sentence"
}
The page requires its mode and focus sponsor, every held perk (hold) or every miss (recap) by its exact name, misses named before thanks, every due date in a welcome checklist, and no other sponsor's name, reach estimate, media value or renewal ask.
Worked examples - every lane, every sample
These are the page's three free samples (fictional events, sponsors and people; every date is illustrative). Each input is exactly what the page sends; each reply is the saved reply the sample replays, shipped as the validating model wrote it; the last line is the page's own check. Every sample has both lanes.
Northfield Infra Conf (community-run, three weeks out) - status
Before the event; 4 sponsors; 1 of 12 cells closed; 2 held for payment; 0 of 4 gates pass; message to Lumvane Data (hold).
Input:
{
"task": "status",
"event": "Event: Northfield Infra Conf 2027; 2027-05-12 to 2027-05-13; community-run; fulfillment run by volunteers with a few hours a week\nAs of: 2027-04-20 (before the event)\nTiers, top first: Platinum, Gold, Lanyard, Silver\nAudience (for the recap): checked in not given; registered not given; count method not given\nHard deadlines: Lanyard print run 2027-04-25 [lanyard]; Slide deck lock 2027-05-05 [slides]; Banner print 2027-04-28 [banner]\nPublished caps: Logo on lanyard cap 1, promised to 2 (Lumvane Data, Kitewire); Welcome speech cap 1, promised to 1 (Hexaplane)",
"matrix": "The matrix, one column per sponsor (cell states: promised, scheduled, delivered, evidenced, partial, missed):\nHexaplane | tier Platinum (top) | payment paid | liaison Ines | on-site rep Ravi | success metric Hiring pipeline for SRE roles | multi-edition | renewal ask yes | budget lock not given | lead ask raffle | recap sent no | report sent no\n Logo on event slides (large) | due 2027-05-05 | owner Marek | scheduled | evidence none\n Welcome speech (3-5 min) | due 2027-05-12 | owner Ines | scheduled | evidence none\n Consented raffle with winner photos | due 2027-05-13 | owner Ines | promised | evidence none\n Logo on pre-event newsletter | due 2027-04-15 | owner Marek | evidenced | evidence newsletter archive link\n Cloud credits for workshop attendees | due 2027-05-12 | owner Marek | promised | evidence none\nLumvane Data | tier Gold | payment partial | liaison Ines | on-site rep none | success metric Workshop attendance | one-off, first-time | renewal ask yes | budget lock not given | lead ask list | recap sent no | report sent no\n Logo on event slides (medium) | due 2027-05-05 | owner Marek | delivered | evidence none\n 60-min workshop slot | due 2027-05-13 | owner Ines | scheduled | evidence none\n Logo on lanyard | due 2027-04-25 | owner none | promised | evidence none\nKitewire | tier Lanyard | payment paid | liaison Marek | on-site rep none | success metric Brand visibility | one-off | renewal ask yes | budget lock not given | lead ask aggregate | recap sent no | report sent no\n Logo on lanyard | due 2027-04-25 | owner Marek | scheduled | evidence none\n Logo on pre-event newsletter | due 2027-04-15 | owner Marek | delivered | evidence none\nOrbitfold | tier Silver | payment invoiced | liaison NONE | on-site rep none | success metric NOT STATED | one-off, first-time | renewal ask no | budget lock not given | lead ask aggregate | recap sent no | report sent no\n Logo on event slides (small) | due 2027-05-05 | owner Marek | promised | evidence none\n Logo on pre-event newsletter | due 2027-04-15 | owner Marek | missed | evidence none",
"facts": "Phase: pre; fulfillment clock: Lanyard print run 2027-04-25; recap due 2027-05-16 (72 hours); stage-2 report due 2027-05-27 (10 business days)\nPayment gate: Lumvane Data partial - perks held; BREACHED, some shipped anyway; Orbitfold invoiced - perks held\nLead capture: Aggregate demographics default; Consented raffle promoted; Bulk attendee lists and badge scanning deleted\nPer sponsor: Hexaplane - onboarding kickoff (top tier, multi-edition relationship, live coordination (Welcome speech (3-5 min), Cloud credits for workshop attendees)), report full (top tier, multi-edition relationship), 1 of 5 cells closed; Lumvane Data - onboarding kickoff (first-time sponsor, live coordination (60-min workshop slot)), report short (the default stage 2), 0 of 3 cells closed; Kitewire - onboarding intake (three or more sponsors make a validated form cheaper than chasing assets one by one), report short (the default stage 2), 0 of 2 cells closed; Orbitfold - onboarding kickoff (first-time sponsor), report recap (nobody plans to renew - the recap is the only report), 0 of 2 cells closed\nFocus sponsor for the message: Lumvane Data; message mode: hold; still promised (held while fees are open): Logo on lanyard; missed or partial: none; closed 0 of 3\nFulfillment gates (0 of 4): Payment gate FAILS; Perk delivery FAILS; Caps FAILS; Ownership FAILS\nSignals to record: Perk delivery: 1 of 12 cells closed with evidence or a make-good (self-set); Assets in hand before each hard deadline, per sponsor (self-set); Recap inside 72 hours and stage 2 inside 10 business days, per sponsor (judged)\nFindings (11):\n[check] no_proof (matrix): Delivered with no evidence: Lumvane Data: Logo on event slides (medium) (2027-05-05); Kitewire: Logo on pre-event newsletter (2027-04-15) - attach the link, screenshot or photo now, not at report time.\n[fix] missed (matrix): Missed or partial with no make-good: Orbitfold: Logo on pre-event newsletter (2027-04-15) - name it to the sponsor yourself, with a make-good in kind, before they find it.\n[check] no_liaison (ownership): Orbitfold has no liaison - name one person per sponsor.\n[check] content_review (day-of): Review the actual content of every sponsored slot before it is confirmed, not just the sponsor's name and topic: Hexaplane - Welcome speech (3-5 min); Lumvane Data - 60-min workshop slot.\n[fix] gate_breach (payment): Lumvane Data is partial, yet Logo on event slides (medium) (delivered), 60-min workshop slot (scheduled) moved past promised - no benefit ships before fees are paid in full.\n[check] held (payment): Orbitfold is invoiced: every perk stays queued behind the invoice. Tell the sponsor through the liaison what is held and why - never as a surprise at the venue door.\n[fix] print_risk (deadlines): Lanyard print run is 2027-04-25 and Lumvane Data has not paid - decide now what goes to the printer; an unpaid logo cannot ship.\n[fix] oversold (caps): Logo on lanyard is capped at 1 but promised to 2 sponsors (Lumvane Data, Kitewire) - an exclusive surface two sponsors hold at once breaks one promise in public.\n[fix] bulk_ask (leads): Lumvane Data asks for an attendee list - deleted, not demoted, at a community-run event: offer aggregate demographics or a consented raffle, or no deal.\n[info] raffle (leads): Hexaplane's raffle is a delivered perk, never an attendee list: say what is collected and who receives it, hand the opt-ins to Hexaplane only, and delete your copy after hand-off.\n[check] measure (measurement): Fulfillment gates: 0 of 4 pass - failing: payment gate, perk delivery, caps, ownership (a self-set bar)."
}
Reply:
{
"task": "status",
"summary": "Pre-event, with Lumvane Data's partial payment already breached by a shipped slide logo and workshop slot, and the lanyard print run due 2027-04-25; resolve Lumvane Data's payment before then.",
"clock": {
"phase": "pre",
"note": "The fulfillment clock is the lanyard print run on 2027-04-25."
},
"payment": [
{
"sponsor": "Hexaplane",
"payment": "paid",
"held": false,
"breach": false,
"note": "Fees are paid in full, so nothing is held."
},
{
"sponsor": "Lumvane Data",
"payment": "partial",
"held": true,
"breach": true,
"note": "Tell Lumvane Data through Ines that fees are still partial, so the lanyard logo stays held even though the slide logo and workshop slot already moved."
},
{
"sponsor": "Kitewire",
"payment": "paid",
"held": false,
"breach": false,
"note": "Fees are paid in full, so nothing is held."
},
{
"sponsor": "Orbitfold",
"payment": "invoiced",
"held": true,
"breach": false,
"note": "Tell Orbitfold that every perk stays held behind the invoice until fees are paid in full."
}
],
"sponsors": [
{
"sponsor": "Hexaplane",
"closed": 1,
"total": 5,
"onboarding": "kickoff",
"report": "full",
"next": "Move Logo on event slides (large) to delivered ahead of the 2027-05-05 slide deck lock."
},
{
"sponsor": "Lumvane Data",
"closed": 0,
"total": 3,
"onboarding": "kickoff",
"report": "short",
"next": "Resolve payment before the 2027-04-25 lanyard print run so Logo on lanyard can ship or get a make-good."
},
{
"sponsor": "Kitewire",
"closed": 0,
"total": 2,
"onboarding": "intake",
"report": "short",
"next": "Move Logo on lanyard to delivered ahead of the 2027-04-25 print run."
},
{
"sponsor": "Orbitfold",
"closed": 0,
"total": 2,
"onboarding": "kickoff",
"report": "recap",
"next": "Name the missed Logo on pre-event newsletter to Orbitfold with a make-good in kind."
}
],
"caps": [
{
"surface": "Logo on lanyard",
"cap": 1,
"sold": 2,
"over": true,
"note": "Promised to both Lumvane Data and Kitewire against a cap of 1 - resolve before the print run."
},
{
"surface": "Welcome speech",
"cap": 1,
"sold": 1,
"over": false,
"note": "Only Hexaplane holds this slot, within the published cap."
}
],
"leads": {
"aggregate": "default",
"raffle": "promoted",
"bulk": "deleted",
"note": "Offer aggregate demographics or a consented raffle to any sponsor asking for more, since bulk attendee lists and badge scanning are deleted at a community-run event."
},
"measurement": [
{
"gate": "Payment gate",
"pass": false
},
{
"gate": "Perk delivery",
"pass": false
},
{
"gate": "Caps",
"pass": false
},
{
"gate": "Ownership",
"pass": false
}
],
"signals": [
"Perk delivery: 1 of 12 cells closed with evidence or a make-good; next edition this would flag chasing assets earlier (my design).",
"Assets in hand before each hard deadline, per sponsor; a miss here next edition would move the deadline earlier (my design).",
"Recap inside 72 hours and stage 2 inside 10 business days, per sponsor; late reports next edition would assign a dedicated owner per sponsor (my design)."
],
"caveats": [
"Lumvane Data's slide logo and workshop slot moved past promised while fees are still partial - no benefit ships before payment in full.",
"Lanyard print run is 2027-04-25 and Lumvane Data has not paid - decide now what goes to the printer.",
"Logo on lanyard is capped at 1 but promised to both Lumvane Data and Kitewire - resolve before the print run.",
"Orbitfold's missed Logo on pre-event newsletter has no make-good - name it to them before they find it."
]
}
The page's check: kept - nothing to flag
Northfield Infra Conf (community-run, three weeks out) - sponsor
Before the event; 4 sponsors; 1 of 12 cells closed; 2 held for payment; 0 of 4 gates pass; message to Lumvane Data (hold).
Input:
{
"task": "sponsor",
"event": "Event: Northfield Infra Conf 2027; 2027-05-12 to 2027-05-13; community-run; fulfillment run by volunteers with a few hours a week\nAs of: 2027-04-20 (before the event)\nTiers, top first: Platinum, Gold, Lanyard, Silver\nAudience (for the recap): checked in not given; registered not given; count method not given\nHard deadlines: Lanyard print run 2027-04-25 [lanyard]; Slide deck lock 2027-05-05 [slides]; Banner print 2027-04-28 [banner]\nPublished caps: Logo on lanyard cap 1, promised to 2 (Lumvane Data, Kitewire); Welcome speech cap 1, promised to 1 (Hexaplane)",
"matrix": "The matrix, one column per sponsor (cell states: promised, scheduled, delivered, evidenced, partial, missed):\nHexaplane | tier Platinum (top) | payment paid | liaison Ines | on-site rep Ravi | success metric Hiring pipeline for SRE roles | multi-edition | renewal ask yes | budget lock not given | lead ask raffle | recap sent no | report sent no\n Logo on event slides (large) | due 2027-05-05 | owner Marek | scheduled | evidence none\n Welcome speech (3-5 min) | due 2027-05-12 | owner Ines | scheduled | evidence none\n Consented raffle with winner photos | due 2027-05-13 | owner Ines | promised | evidence none\n Logo on pre-event newsletter | due 2027-04-15 | owner Marek | evidenced | evidence newsletter archive link\n Cloud credits for workshop attendees | due 2027-05-12 | owner Marek | promised | evidence none\nLumvane Data | tier Gold | payment partial | liaison Ines | on-site rep none | success metric Workshop attendance | one-off, first-time | renewal ask yes | budget lock not given | lead ask list | recap sent no | report sent no\n Logo on event slides (medium) | due 2027-05-05 | owner Marek | delivered | evidence none\n 60-min workshop slot | due 2027-05-13 | owner Ines | scheduled | evidence none\n Logo on lanyard | due 2027-04-25 | owner none | promised | evidence none\nKitewire | tier Lanyard | payment paid | liaison Marek | on-site rep none | success metric Brand visibility | one-off | renewal ask yes | budget lock not given | lead ask aggregate | recap sent no | report sent no\n Logo on lanyard | due 2027-04-25 | owner Marek | scheduled | evidence none\n Logo on pre-event newsletter | due 2027-04-15 | owner Marek | delivered | evidence none\nOrbitfold | tier Silver | payment invoiced | liaison NONE | on-site rep none | success metric NOT STATED | one-off, first-time | renewal ask no | budget lock not given | lead ask aggregate | recap sent no | report sent no\n Logo on event slides (small) | due 2027-05-05 | owner Marek | promised | evidence none\n Logo on pre-event newsletter | due 2027-04-15 | owner Marek | missed | evidence none",
"facts": "Phase: pre; fulfillment clock: Lanyard print run 2027-04-25; recap due 2027-05-16 (72 hours); stage-2 report due 2027-05-27 (10 business days)\nPayment gate: Lumvane Data partial - perks held; BREACHED, some shipped anyway; Orbitfold invoiced - perks held\nLead capture: Aggregate demographics default; Consented raffle promoted; Bulk attendee lists and badge scanning deleted\nPer sponsor: Hexaplane - onboarding kickoff (top tier, multi-edition relationship, live coordination (Welcome speech (3-5 min), Cloud credits for workshop attendees)), report full (top tier, multi-edition relationship), 1 of 5 cells closed; Lumvane Data - onboarding kickoff (first-time sponsor, live coordination (60-min workshop slot)), report short (the default stage 2), 0 of 3 cells closed; Kitewire - onboarding intake (three or more sponsors make a validated form cheaper than chasing assets one by one), report short (the default stage 2), 0 of 2 cells closed; Orbitfold - onboarding kickoff (first-time sponsor), report recap (nobody plans to renew - the recap is the only report), 0 of 2 cells closed\nFocus sponsor for the message: Lumvane Data; message mode: hold; still promised (held while fees are open): Logo on lanyard; missed or partial: none; closed 0 of 3\nFulfillment gates (0 of 4): Payment gate FAILS; Perk delivery FAILS; Caps FAILS; Ownership FAILS\nSignals to record: Perk delivery: 1 of 12 cells closed with evidence or a make-good (self-set); Assets in hand before each hard deadline, per sponsor (self-set); Recap inside 72 hours and stage 2 inside 10 business days, per sponsor (judged)\nFindings (11):\n[check] no_proof (matrix): Delivered with no evidence: Lumvane Data: Logo on event slides (medium) (2027-05-05); Kitewire: Logo on pre-event newsletter (2027-04-15) - attach the link, screenshot or photo now, not at report time.\n[fix] missed (matrix): Missed or partial with no make-good: Orbitfold: Logo on pre-event newsletter (2027-04-15) - name it to the sponsor yourself, with a make-good in kind, before they find it.\n[check] no_liaison (ownership): Orbitfold has no liaison - name one person per sponsor.\n[check] content_review (day-of): Review the actual content of every sponsored slot before it is confirmed, not just the sponsor's name and topic: Hexaplane - Welcome speech (3-5 min); Lumvane Data - 60-min workshop slot.\n[fix] gate_breach (payment): Lumvane Data is partial, yet Logo on event slides (medium) (delivered), 60-min workshop slot (scheduled) moved past promised - no benefit ships before fees are paid in full.\n[check] held (payment): Orbitfold is invoiced: every perk stays queued behind the invoice. Tell the sponsor through the liaison what is held and why - never as a surprise at the venue door.\n[fix] print_risk (deadlines): Lanyard print run is 2027-04-25 and Lumvane Data has not paid - decide now what goes to the printer; an unpaid logo cannot ship.\n[fix] oversold (caps): Logo on lanyard is capped at 1 but promised to 2 sponsors (Lumvane Data, Kitewire) - an exclusive surface two sponsors hold at once breaks one promise in public.\n[fix] bulk_ask (leads): Lumvane Data asks for an attendee list - deleted, not demoted, at a community-run event: offer aggregate demographics or a consented raffle, or no deal.\n[info] raffle (leads): Hexaplane's raffle is a delivered perk, never an attendee list: say what is collected and who receives it, hand the opt-ins to Hexaplane only, and delete your copy after hand-off.\n[check] measure (measurement): Fulfillment gates: 0 of 4 pass - failing: payment gate, perk delivery, caps, ownership (a self-set bar)."
}
Reply:
{
"task": "sponsor",
"mode": "hold",
"to": "Lumvane Data",
"subject": "Lumvane Data: Clear Your Balance to Release the Lanyard Logo",
"body": "Dear Lumvane Data,\n\nYour account is currently showing a partial payment, and until it is settled, your Logo on lanyard placement stays on hold and has not gone out yet.\n\nThe lanyard print run is 2027-04-25, so we would need the balance cleared before then to include your logo.\n\nFor reference, your Logo on event slides (medium) has already been delivered, and your 60-min workshop slot is scheduled for 2027-05-13.\n\nTo release the held placement, please pay the remaining balance on your invoice. Let us know once that's settled or if you have questions about the amount.\n\nBest,\nInes",
"held": [
"Logo on lanyard"
],
"misses": [],
"note": "Before sending, decide which sponsor's logo goes on the single lanyard slot (Lumvane Data or Kitewire) and get Lumvane Data's payment status confirmed ahead of the 2027-04-25 print run."
}
The page's check: kept - nothing to flag
Riverside Student Hack (five days after) - status
After the event; 3 sponsors; 5 of 8 cells closed; 0 held for payment; 3 of 4 gates pass; message to Cobalt Labs (recap).
Input:
{
"task": "status",
"event": "Event: Riverside Student Hack; 2027-03-05 to 2027-03-07; community-run; fulfillment run by volunteers with a few hours a week\nAs of: 2027-03-12 (after the event)\nTiers, top first: Gold, Silver, Prize track\nAudience (for the recap): checked in 212; registered 260; count method unique badge pickup, sponsor and organizer staff excluded\nHard deadlines: T-shirt print order 2027-02-20 [t-shirt]\nPublished caps: none entered",
"matrix": "The matrix, one column per sponsor (cell states: promised, scheduled, delivered, evidenced, partial, missed):\nVectorly | tier Gold (top) | payment paid | liaison Sam | on-site rep Jo Park | success metric API adoption in submissions | multi-edition | renewal ask yes | budget lock 2027-03-15 | lead ask aggregate | recap sent 2027-03-09 | report sent no\n Logo on hacker t-shirt | due 2027-02-20 | owner Ade | evidenced | evidence photo row01-shirt\n API credits for every team | due 2027-03-05 | owner Sam | evidenced | evidence credit code log\n Opening pitch (3 min) | due 2027-03-05 | owner Sam | evidenced | evidence program link\n Logo on venue screen loop | due 2027-03-05 | owner Ade | partial | evidence loop log\nCobalt Labs | tier Prize track | payment paid | liaison Sam | on-site rep none | success metric Submissions using the Cobalt SDK | one-off, first-time | renewal ask yes | budget lock not given | lead ask aggregate | recap sent no | report sent no\n Sponsored prize track | due 2027-03-07 | owner Sam | evidenced | evidence judging form export\n Logo on hacker t-shirt | due 2027-02-20 | owner Ade | missed | evidence none\nPinecrest Bank | tier Silver | payment paid | liaison Ade | on-site rep none | success metric NOT STATED | one-off | renewal ask no | budget lock not given | lead ask aggregate | recap sent 2027-03-08 | report sent no\n Logo on event page | due 2027-02-15 | owner Ade | evidenced | evidence event page link\n Mentor table | due 2027-03-06 | owner Ade | delivered | evidence none",
"facts": "Phase: post; fulfillment clock: no upcoming hard deadline; recap due 2027-03-10 (72 hours); stage-2 report due 2027-03-19 (10 business days)\nPayment gate: every sponsor paid\nLead capture: Aggregate demographics default; Consented raffle available; Bulk attendee lists and badge scanning deleted\nPer sponsor: Vectorly - onboarding kickoff (top tier, multi-edition relationship, live coordination (Opening pitch (3 min))), report short (top tier, multi-edition relationship - shortened to the short form by the budget lock on 2027-03-15), 3 of 4 cells closed; Cobalt Labs - onboarding kickoff (first-time sponsor, live coordination (Sponsored prize track)), report short (the default stage 2), 1 of 2 cells closed; Pinecrest Bank - onboarding intake (three or more sponsors make a validated form cheaper than chasing assets one by one), report recap (nobody plans to renew - the recap is the only report), 1 of 2 cells closed\nFocus sponsor for the message: Cobalt Labs; message mode: recap; still promised (held while fees are open): none; missed or partial: Logo on hacker t-shirt; closed 1 of 2\nFulfillment gates (3 of 4): Payment gate passes; Perk delivery FAILS; Caps passes; Ownership passes\nSignals to record: Perk delivery: 5 of 8 cells closed with evidence or a make-good (self-set); Assets in hand before each hard deadline, per sponsor (self-set); Recap inside 72 hours and stage 2 inside 10 business days, per sponsor (judged)\nFindings (5):\n[check] no_proof (matrix): Delivered with no evidence: Pinecrest Bank: Mentor table (2027-03-06) - attach the link, screenshot or photo now, not at report time.\n[fix] missed (matrix): Missed or partial with no make-good: Vectorly: Logo on venue screen loop (2027-03-05); Cobalt Labs: Logo on hacker t-shirt (2027-02-20) - name it to the sponsor yourself, with a make-good in kind, before they find it.\n[fix] recap_late (reports): Cobalt Labs: the recap was due by 2027-03-10 (72 hours) and is not marked sent - send it today, at recap depth if the data is thin.\n[fix] open_cells (reports): 3 cells still open after the event - every cell is evidenced, or named with its make-good, before a report goes out.\n[check] measure (measurement): Fulfillment gates: 3 of 4 pass - failing: perk delivery (a self-set bar)."
}
Reply:
{
"task": "status",
"summary": "Post-event, with Cobalt Labs' missed t-shirt logo still lacking a make-good and its 72-hour recap overdue; send the recap today and agree the make-good.",
"clock": {
"phase": "post",
"note": "The recap was due 2027-03-10 (72 hours) and the stage-2 report is due 2027-03-19 (10 business days)."
},
"payment": [
{
"sponsor": "Vectorly",
"payment": "paid",
"held": false,
"breach": false,
"note": "Fees are paid in full, so nothing is held."
},
{
"sponsor": "Cobalt Labs",
"payment": "paid",
"held": false,
"breach": false,
"note": "Fees are paid in full, so nothing is held."
},
{
"sponsor": "Pinecrest Bank",
"payment": "paid",
"held": false,
"breach": false,
"note": "Fees are paid in full, so nothing is held."
}
],
"sponsors": [
{
"sponsor": "Vectorly",
"closed": 3,
"total": 4,
"onboarding": "kickoff",
"report": "short",
"next": "Resolve Logo on venue screen loop with a make-good, since it is still partial."
},
{
"sponsor": "Cobalt Labs",
"closed": 1,
"total": 2,
"onboarding": "kickoff",
"report": "short",
"next": "Name the missed Logo on hacker t-shirt to Cobalt Labs with a make-good in kind."
},
{
"sponsor": "Pinecrest Bank",
"closed": 1,
"total": 2,
"onboarding": "intake",
"report": "recap",
"next": "Attach evidence for Mentor table now, not at report time."
}
],
"caps": [],
"leads": {
"aggregate": "default",
"raffle": "available",
"bulk": "deleted",
"note": "Offer aggregate demographics or a consented raffle to any sponsor asking for more, since bulk attendee lists and badge scanning are deleted at a community-run event."
},
"measurement": [
{
"gate": "Payment gate",
"pass": true
},
{
"gate": "Perk delivery",
"pass": false
},
{
"gate": "Caps",
"pass": true
},
{
"gate": "Ownership",
"pass": true
}
],
"signals": [
"Perk delivery: 5 of 8 cells closed with evidence or a make-good; a low rate next edition would require evidence at delivery time (my design).",
"Assets in hand before each hard deadline, per sponsor; a miss here next edition would move the t-shirt order earlier (my design).",
"Recap inside 72 hours and stage 2 inside 10 business days, per sponsor; a late recap next edition would add a backup sender (my design)."
],
"caveats": [
"Vectorly: Logo on venue screen loop and Cobalt Labs: Logo on hacker t-shirt are partial or missed with no make-good - name them to each sponsor before they find it.",
"Cobalt Labs' recap was due by 2027-03-10 and is not marked sent - send it today, at recap depth if the data is thin.",
"3 cells are still open after the event - every cell needs evidence or a named make-good before a report goes out.",
"Pinecrest Bank's Mentor table is delivered with no evidence - attach the link, screenshot or photo now."
]
}
The page's check: kept - nothing to flag
Riverside Student Hack (five days after) - sponsor
After the event; 3 sponsors; 5 of 8 cells closed; 0 held for payment; 3 of 4 gates pass; message to Cobalt Labs (recap).
Input:
{
"task": "sponsor",
"event": "Event: Riverside Student Hack; 2027-03-05 to 2027-03-07; community-run; fulfillment run by volunteers with a few hours a week\nAs of: 2027-03-12 (after the event)\nTiers, top first: Gold, Silver, Prize track\nAudience (for the recap): checked in 212; registered 260; count method unique badge pickup, sponsor and organizer staff excluded\nHard deadlines: T-shirt print order 2027-02-20 [t-shirt]\nPublished caps: none entered",
"matrix": "The matrix, one column per sponsor (cell states: promised, scheduled, delivered, evidenced, partial, missed):\nVectorly | tier Gold (top) | payment paid | liaison Sam | on-site rep Jo Park | success metric API adoption in submissions | multi-edition | renewal ask yes | budget lock 2027-03-15 | lead ask aggregate | recap sent 2027-03-09 | report sent no\n Logo on hacker t-shirt | due 2027-02-20 | owner Ade | evidenced | evidence photo row01-shirt\n API credits for every team | due 2027-03-05 | owner Sam | evidenced | evidence credit code log\n Opening pitch (3 min) | due 2027-03-05 | owner Sam | evidenced | evidence program link\n Logo on venue screen loop | due 2027-03-05 | owner Ade | partial | evidence loop log\nCobalt Labs | tier Prize track | payment paid | liaison Sam | on-site rep none | success metric Submissions using the Cobalt SDK | one-off, first-time | renewal ask yes | budget lock not given | lead ask aggregate | recap sent no | report sent no\n Sponsored prize track | due 2027-03-07 | owner Sam | evidenced | evidence judging form export\n Logo on hacker t-shirt | due 2027-02-20 | owner Ade | missed | evidence none\nPinecrest Bank | tier Silver | payment paid | liaison Ade | on-site rep none | success metric NOT STATED | one-off | renewal ask no | budget lock not given | lead ask aggregate | recap sent 2027-03-08 | report sent no\n Logo on event page | due 2027-02-15 | owner Ade | evidenced | evidence event page link\n Mentor table | due 2027-03-06 | owner Ade | delivered | evidence none",
"facts": "Phase: post; fulfillment clock: no upcoming hard deadline; recap due 2027-03-10 (72 hours); stage-2 report due 2027-03-19 (10 business days)\nPayment gate: every sponsor paid\nLead capture: Aggregate demographics default; Consented raffle available; Bulk attendee lists and badge scanning deleted\nPer sponsor: Vectorly - onboarding kickoff (top tier, multi-edition relationship, live coordination (Opening pitch (3 min))), report short (top tier, multi-edition relationship - shortened to the short form by the budget lock on 2027-03-15), 3 of 4 cells closed; Cobalt Labs - onboarding kickoff (first-time sponsor, live coordination (Sponsored prize track)), report short (the default stage 2), 1 of 2 cells closed; Pinecrest Bank - onboarding intake (three or more sponsors make a validated form cheaper than chasing assets one by one), report recap (nobody plans to renew - the recap is the only report), 1 of 2 cells closed\nFocus sponsor for the message: Cobalt Labs; message mode: recap; still promised (held while fees are open): none; missed or partial: Logo on hacker t-shirt; closed 1 of 2\nFulfillment gates (3 of 4): Payment gate passes; Perk delivery FAILS; Caps passes; Ownership passes\nSignals to record: Perk delivery: 5 of 8 cells closed with evidence or a make-good (self-set); Assets in hand before each hard deadline, per sponsor (self-set); Recap inside 72 hours and stage 2 inside 10 business days, per sponsor (judged)\nFindings (5):\n[check] no_proof (matrix): Delivered with no evidence: Pinecrest Bank: Mentor table (2027-03-06) - attach the link, screenshot or photo now, not at report time.\n[fix] missed (matrix): Missed or partial with no make-good: Vectorly: Logo on venue screen loop (2027-03-05); Cobalt Labs: Logo on hacker t-shirt (2027-02-20) - name it to the sponsor yourself, with a make-good in kind, before they find it.\n[fix] recap_late (reports): Cobalt Labs: the recap was due by 2027-03-10 (72 hours) and is not marked sent - send it today, at recap depth if the data is thin.\n[fix] open_cells (reports): 3 cells still open after the event - every cell is evidenced, or named with its make-good, before a report goes out.\n[check] measure (measurement): Fulfillment gates: 3 of 4 pass - failing: perk delivery (a self-set bar)."
}
Reply:
{
"task": "sponsor",
"mode": "recap",
"to": "Cobalt Labs",
"subject": "Cobalt Labs: Riverside Student Hack Recap",
"body": "Dear Cobalt Labs,\n\nLogo on hacker t-shirt was due 2027-02-20 and was missed; make-good: [make-good to agree].\n\nThank you for sponsoring the Prize track at Riverside Student Hack - having Cobalt Labs there added real value for the teams.\n\nFor the event, 212 people checked in and 260 registered, counted by unique badge pickup, sponsor and organizer staff excluded.\n\nYour column closed at 1 of 2.\n\n[3-5 photos]\n\nBest,\nSam",
"held": [],
"misses": [
"Logo on hacker t-shirt"
],
"note": "Agree a make-good for the missed t-shirt logo and send this overdue recap today, since it was due 2027-03-10."
}
The page's check: kept - nothing to flag
Cloudline Summit (company-run, three weeks out) - status
Before the event; 3 sponsors; 1 of 8 cells closed; 0 held for payment; 3 of 4 gates pass; message to Arcmesh (welcome).
Input:
{
"task": "status",
"event": "Event: Cloudline Summit 2027; 2027-06-08 to 2027-06-09; company- or foundation-run; fulfillment run by a dedicated sponsorship lead\nAs of: 2027-05-20 (before the event)\nTiers, top first: Diamond, Gold, Startup\nAudience (for the recap): checked in not given; registered not given; count method not given\nHard deadlines: Badge print run 2027-05-25 [badge]; Banner print 2027-05-15 [banner]\nPublished caps: Logo on badge cap 2, promised to 2 (Arcmesh, Northbeam); Keynote cap 1, promised to 1 (Arcmesh)",
"matrix": "The matrix, one column per sponsor (cell states: promised, scheduled, delivered, evidenced, partial, missed):\nArcmesh | tier Diamond (top) | payment paid | liaison Leila | on-site rep Tomas | success metric Qualified pipeline meetings | multi-edition | renewal ask yes | budget lock 2027-06-01 | lead ask scan | recap sent no | report sent no\n Keynote session (20 min) | due 2027-06-08 | owner Leila | scheduled | evidence none\n Consent-bounded badge scanning | due 2027-06-08 | owner Chen | scheduled | evidence none\n Logo on main-stage banner | due 2027-05-15 | owner Chen | scheduled - LATE | evidence none\n Logo on badge | due 2027-05-25 | owner Chen | scheduled | evidence none\nNorthbeam | tier Gold | payment paid | liaison Leila | on-site rep none | success metric Recruiting signups | one-off, first-time | renewal ask yes | budget lock not given | lead ask list | recap sent no | report sent no\n Booth (large) | due 2027-06-07 | owner Chen | scheduled | evidence none\n Logo on badge | due 2027-05-25 | owner Chen | promised | evidence none\nTinyhop | tier Startup | payment paid | liaison Chen | on-site rep none | success metric Demo signups | one-off, first-time | renewal ask yes | budget lock not given | lead ask aggregate | recap sent no | report sent no\n Demo slot (5 min) | due 2027-06-09 | owner Leila | promised | evidence none\n Logo on event page | due 2027-05-01 | owner none | delivered | evidence event page link",
"facts": "Phase: pre; fulfillment clock: Badge print run 2027-05-25; recap due 2027-06-12 (72 hours); stage-2 report due 2027-06-23 (10 business days)\nPayment gate: every sponsor paid\nLead capture: Aggregate demographics default; Consented raffle available; Consent-bounded badge scanning available\nPer sponsor: Arcmesh - onboarding kickoff (top tier, multi-edition relationship, live coordination (Keynote session (20 min))), report short (top tier, multi-edition relationship, a named success metric with a dedicated lead - shortened to the short form by the budget lock on 2027-06-01), 0 of 4 cells closed; Northbeam - onboarding kickoff (first-time sponsor), report full (a named success metric with a dedicated lead), 0 of 2 cells closed; Tinyhop - onboarding kickoff (first-time sponsor, live coordination (Demo slot (5 min))), report full (a named success metric with a dedicated lead), 1 of 2 cells closed\nFocus sponsor for the message: Arcmesh; message mode: welcome; still promised (held while fees are open): none; missed or partial: none; closed 0 of 4\nFulfillment gates (3 of 4): Payment gate passes; Perk delivery FAILS; Caps passes; Ownership passes\nSignals to record: Perk delivery: 1 of 8 cells closed with evidence or a make-good (self-set); Assets in hand before each hard deadline, per sponsor (self-set); Recap inside 72 hours and stage 2 inside 10 business days, per sponsor (judged)\nFindings (6):\n[fix] late (matrix): 1 cell past due and not delivered: Arcmesh: Logo on main-stage banner (2027-05-15).\n[check] content_review (day-of): Review the actual content of every sponsored slot before it is confirmed, not just the sponsor's name and topic: Arcmesh - Keynote session (20 min); Tinyhop - Demo slot (5 min).\n[fix] print_missed (deadlines): Banner print (2027-05-15) has passed with Arcmesh - Logo on main-stage banner not delivered - after a print run it is a make-good negotiation, not a perk.\n[check] list_company (leads): Northbeam asks for an attendee list - even company-run, only consent-bounded scans or opt-ins are deliverable.\n[check] lock_early (reports): Arcmesh's budget locks 2027-06-01, before the event - hand them to the renewal motion for an on-site ask; the report will land too late.\n[check] measure (measurement): Fulfillment gates: 3 of 4 pass - failing: perk delivery (a self-set bar)."
}
Reply:
{
"task": "status",
"summary": "Pre-event, with Arcmesh's Logo on main-stage banner past the 2027-05-15 banner print run undelivered; tell Arcmesh through Leila and agree a make-good.",
"clock": {
"phase": "pre",
"note": "The fulfillment clock runs to the Badge print run on 2027-05-25."
},
"payment": [
{
"sponsor": "Arcmesh",
"payment": "paid",
"held": false,
"breach": false,
"note": "Nothing is held; fees are paid in full."
},
{
"sponsor": "Northbeam",
"payment": "paid",
"held": false,
"breach": false,
"note": "Nothing is held; fees are paid in full."
},
{
"sponsor": "Tinyhop",
"payment": "paid",
"held": false,
"breach": false,
"note": "Nothing is held; fees are paid in full."
}
],
"sponsors": [
{
"sponsor": "Arcmesh",
"closed": 0,
"total": 4,
"onboarding": "kickoff",
"report": "short",
"next": "Move Logo on main-stage banner, now past its 2027-05-15 print run."
},
{
"sponsor": "Northbeam",
"closed": 0,
"total": 2,
"onboarding": "kickoff",
"report": "full",
"next": "Move Logo on badge toward delivery before its 2027-05-25 due date."
},
{
"sponsor": "Tinyhop",
"closed": 1,
"total": 2,
"onboarding": "kickoff",
"report": "full",
"next": "Move Demo slot (5 min) toward its 2027-06-09 due date."
}
],
"caps": [
{
"surface": "Logo on badge",
"cap": 2,
"sold": 2,
"over": false,
"note": "Sold to its full cap of 2, with no oversell."
},
{
"surface": "Keynote",
"cap": 1,
"sold": 1,
"over": false,
"note": "Sold to its full cap of 1, with no oversell."
}
],
"leads": {
"aggregate": "default",
"raffle": "available",
"bulk": "available",
"note": "Offer consent-bounded badge scanning, not a bulk attendee list, to any sponsor asking for more."
},
"measurement": [
{
"gate": "Payment gate",
"pass": true
},
{
"gate": "Perk delivery",
"pass": false
},
{
"gate": "Caps",
"pass": true
},
{
"gate": "Ownership",
"pass": true
}
],
"signals": [
"Perk delivery is 1 of 8 cells closed with evidence or a make-good; next edition this would set an evidence check at each print run before dates are promised to sponsors (own design).",
"Assets in hand before each hard deadline, per sponsor; next edition this would require each owner to confirm assets before the print run itself (own design).",
"Recap inside 72 hours and stage 2 inside 10 business days, per sponsor; next edition this would score each sponsor's recap and report against those same deadlines (own design)."
],
"caveats": [
"[fix] 1 cell past due and not delivered: Arcmesh: Logo on main-stage banner (2027-05-15).",
"[fix] Banner print (2027-05-15) has passed with Arcmesh: Logo on main-stage banner not delivered; after a print run it is a make-good negotiation, not a perk.",
"[check] Northbeam asks for an attendee list; even company-run, only consent-bounded scans or opt-ins are deliverable.",
"[check] Arcmesh's budget locks 2027-06-01, before the event; hand them to the renewal motion for an on-site ask since the report will land too late."
]
}
The page's check: kept - nothing to flag
Cloudline Summit (company-run, three weeks out) - sponsor
Before the event; 3 sponsors; 1 of 8 cells closed; 0 held for payment; 3 of 4 gates pass; message to Arcmesh (welcome).
Input:
{
"task": "sponsor",
"event": "Event: Cloudline Summit 2027; 2027-06-08 to 2027-06-09; company- or foundation-run; fulfillment run by a dedicated sponsorship lead\nAs of: 2027-05-20 (before the event)\nTiers, top first: Diamond, Gold, Startup\nAudience (for the recap): checked in not given; registered not given; count method not given\nHard deadlines: Badge print run 2027-05-25 [badge]; Banner print 2027-05-15 [banner]\nPublished caps: Logo on badge cap 2, promised to 2 (Arcmesh, Northbeam); Keynote cap 1, promised to 1 (Arcmesh)",
"matrix": "The matrix, one column per sponsor (cell states: promised, scheduled, delivered, evidenced, partial, missed):\nArcmesh | tier Diamond (top) | payment paid | liaison Leila | on-site rep Tomas | success metric Qualified pipeline meetings | multi-edition | renewal ask yes | budget lock 2027-06-01 | lead ask scan | recap sent no | report sent no\n Keynote session (20 min) | due 2027-06-08 | owner Leila | scheduled | evidence none\n Consent-bounded badge scanning | due 2027-06-08 | owner Chen | scheduled | evidence none\n Logo on main-stage banner | due 2027-05-15 | owner Chen | scheduled - LATE | evidence none\n Logo on badge | due 2027-05-25 | owner Chen | scheduled | evidence none\nNorthbeam | tier Gold | payment paid | liaison Leila | on-site rep none | success metric Recruiting signups | one-off, first-time | renewal ask yes | budget lock not given | lead ask list | recap sent no | report sent no\n Booth (large) | due 2027-06-07 | owner Chen | scheduled | evidence none\n Logo on badge | due 2027-05-25 | owner Chen | promised | evidence none\nTinyhop | tier Startup | payment paid | liaison Chen | on-site rep none | success metric Demo signups | one-off, first-time | renewal ask yes | budget lock not given | lead ask aggregate | recap sent no | report sent no\n Demo slot (5 min) | due 2027-06-09 | owner Leila | promised | evidence none\n Logo on event page | due 2027-05-01 | owner none | delivered | evidence event page link",
"facts": "Phase: pre; fulfillment clock: Badge print run 2027-05-25; recap due 2027-06-12 (72 hours); stage-2 report due 2027-06-23 (10 business days)\nPayment gate: every sponsor paid\nLead capture: Aggregate demographics default; Consented raffle available; Consent-bounded badge scanning available\nPer sponsor: Arcmesh - onboarding kickoff (top tier, multi-edition relationship, live coordination (Keynote session (20 min))), report short (top tier, multi-edition relationship, a named success metric with a dedicated lead - shortened to the short form by the budget lock on 2027-06-01), 0 of 4 cells closed; Northbeam - onboarding kickoff (first-time sponsor), report full (a named success metric with a dedicated lead), 0 of 2 cells closed; Tinyhop - onboarding kickoff (first-time sponsor, live coordination (Demo slot (5 min))), report full (a named success metric with a dedicated lead), 1 of 2 cells closed\nFocus sponsor for the message: Arcmesh; message mode: welcome; still promised (held while fees are open): none; missed or partial: none; closed 0 of 4\nFulfillment gates (3 of 4): Payment gate passes; Perk delivery FAILS; Caps passes; Ownership passes\nSignals to record: Perk delivery: 1 of 8 cells closed with evidence or a make-good (self-set); Assets in hand before each hard deadline, per sponsor (self-set); Recap inside 72 hours and stage 2 inside 10 business days, per sponsor (judged)\nFindings (6):\n[fix] late (matrix): 1 cell past due and not delivered: Arcmesh: Logo on main-stage banner (2027-05-15).\n[check] content_review (day-of): Review the actual content of every sponsored slot before it is confirmed, not just the sponsor's name and topic: Arcmesh - Keynote session (20 min); Tinyhop - Demo slot (5 min).\n[fix] print_missed (deadlines): Banner print (2027-05-15) has passed with Arcmesh - Logo on main-stage banner not delivered - after a print run it is a make-good negotiation, not a perk.\n[check] list_company (leads): Northbeam asks for an attendee list - even company-run, only consent-bounded scans or opt-ins are deliverable.\n[check] lock_early (reports): Arcmesh's budget locks 2027-06-01, before the event - hand them to the renewal motion for an on-site ask; the report will land too late.\n[check] measure (measurement): Fulfillment gates: 3 of 4 pass - failing: perk delivery (a self-set bar)."
}
Reply:
{
"task": "sponsor",
"mode": "welcome",
"to": "Arcmesh",
"subject": "Your Cloudline Summit 2027 sponsor perks",
"body": "Hello Arcmesh,\n\nWelcome aboard as our Diamond sponsor for Cloudline Summit 2027, running 2027-06-08 to 2027-06-09. Here is where each of your sponsor perks stands right now.\n\nKeynote session (20 min) - due 2027-06-08, scheduled. Please send us [keynote slide deck, format] and [speaker name, title and headshot, format] so we can prepare the session.\n\nConsent-bounded badge scanning - due 2027-06-08, scheduled. Please send us [scanning app or device details, format] so Chen can set it up for the floor.\n\nLogo on badge - due 2027-05-25, scheduled. Please send us [logo file, format] ahead of the badge print run.\n\nLogo on main-stage banner - due 2027-05-15: this one has slipped past the banner print run and is now [make-good to agree]. We are sorry for the delay and will follow up with an alternative.\n\nLet us know if you have any questions.\n\nBest,\nLeila",
"held": [],
"misses": [],
"note": "Settle the make-good for the late Logo on main-stage banner with Arcmesh before sending, since the banner print run has passed."
}
The page's check: kept - nothing to flag
The matrix CSV for the first sample
sponsor,tier,payment,perk,due,owner,state,late,evidence,make_good
Hexaplane,Platinum,paid,Logo on event slides (large),2027-05-05,Marek,scheduled,,,
Hexaplane,Platinum,paid,Welcome speech (3-5 min),2027-05-12,Ines,scheduled,,,
Hexaplane,Platinum,paid,Consented raffle with winner photos,2027-05-13,Ines,promised,,,
Hexaplane,Platinum,paid,Logo on pre-event newsletter,2027-04-15,Marek,evidenced,,newsletter archive link,
Hexaplane,Platinum,paid,Cloud credits for workshop attendees,2027-05-12,Marek,promised,,,
Lumvane Data,Gold,partial,Logo on event slides (medium),2027-05-05,Marek,delivered,,,
Lumvane Data,Gold,partial,60-min workshop slot,2027-05-13,Ines,scheduled,,,
Lumvane Data,Gold,partial,Logo on lanyard,2027-04-25,,promised,,,
Kitewire,Lanyard,paid,Logo on lanyard,2027-04-25,Marek,scheduled,,,
Kitewire,Lanyard,paid,Logo on pre-event newsletter,2027-04-15,Marek,delivered,,,
Orbitfold,Silver,invoiced,Logo on event slides (small),2027-05-05,Marek,promised,,,
Orbitfold,Silver,invoiced,Logo on pre-event newsletter,2027-04-15,Marek,missed,,,
Build the input yourself
Load the engine in node (global.window = global; require("./promisekit.js"); require("./promisereply.js")), then:
const K = PromiseKit, R = PromiseReply;
const f = K.form({ name: "My Conf", start: "2027-05-12", end: "2027-05-13", asOf: "2027-04-20", pole: "community", tiers: "Gold, Silver",
sponsors: fs.readFileSync("sponsors.csv", "utf8"), perks: fs.readFileSync("perks.csv", "utf8"),
deadlines: "deadline,date,surface\nLanyard print run,2027-04-25,lanyard", caps: "surface,cap\nLogo on lanyard,1" });
// f.sp (name, pay, cells, instrument, depth, evidenced, total), f.held, f.breach, f.clockDl, f.capRows, f.leadRungs
// f.phase, f.recapDue, f.reportDue, f.focus, f.mode, f.measure, f.findings
K.matrixCSV(f) // sponsor, tier, payment, perk, due, owner, state, late, ...
const b = K.buildInput(f, "status"); // or "sponsor"
const wire = K.toWire(b.input); // POST this to /estimate and /run
// then: const reply = R.normalize(R.parseReply(job.output.output), "status");
// 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="paste-your-token-here" # from https://sponsor-promises.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"}
}
import json, urllib.request
BASE = "https://api.skillsafe.ai/v1/app-api"
TOKEN = "paste-your-token-here" # from https://sponsor-promises.skillsafe.ai/tokens.html
def api(method, path, body=None, headers=None):
req = urllib.request.Request(BASE + path, method=method,
data=None if body is None else json.dumps(body).encode(),
headers={"Content-Type": "application/json", **({"Authorization": "Bearer " + TOKEN} if TOKEN else {}), **(headers or {})})
with urllib.request.urlopen(req) as r:
env = json.load(r)
if env.get("error"):
raise RuntimeError(env["error"])
return env["data"]
// sponsor-promises.mjs -- Node 18+ (global fetch)
const BASE = "https://api.skillsafe.ai/v1/app-api";
let TOKEN = "paste-your-token-here"; // from https://sponsor-promises.skillsafe.ai/tokens.html
async function api(method, path, body, headers = {}) {
const r = await fetch(BASE + path, { method, headers: { "Content-Type": "application/json",
...(TOKEN ? { Authorization: "Bearer " + TOKEN } : {}), ...headers },
body: body === undefined ? undefined : JSON.stringify(body) });
const env = await r.json();
if (env.error) throw new Error(env.error.code + ": " + env.error.message);
return env.data;
}
package main
import ("bytes"; "encoding/json"; "fmt"; "net/http")
const base = "https://api.skillsafe.ai/v1/app-api"
var token = "paste-your-token-here" // from https://sponsor-promises.skillsafe.ai/tokens.html
func api(method, path string, body any, headers map[string]string) (map[string]any, error) {
var buf bytes.Buffer
if body != nil { json.NewEncoder(&buf).Encode(body) }
req, _ := http.NewRequest(method, base+path, &buf)
req.Header.Set("Content-Type", "application/json")
if token != "" { req.Header.Set("Authorization", "Bearer "+token) }
for k, v := range headers { req.Header.Set(k, v) }
res, err := http.DefaultClient.Do(req)
if err != nil { return nil, err }
defer res.Body.Close()
var env struct { Data map[string]any; Error map[string]any }
json.NewDecoder(res.Body).Decode(&env)
if env.Error != nil { return nil, fmt.Errorf("%v", env.Error) }
return env.Data, nil
}
// SponsorPromises.java -- Java 17+, with com.fasterxml.jackson.core:jackson-databind
import com.fasterxml.jackson.databind.*;
import java.net.URI; import java.net.http.*; import java.util.*;
public class SponsorPromises {
static final String BASE = "https://api.skillsafe.ai/v1/app-api";
static String token = "paste-your-token-here"; // from https://sponsor-promises.skillsafe.ai/tokens.html
static final ObjectMapper M = new ObjectMapper();
static final HttpClient C = HttpClient.newHttpClient();
static JsonNode api(String method, String path, Object body, Map<String, String> headers) throws Exception {
var b = HttpRequest.newBuilder(URI.create(BASE + path)).header("Content-Type", "application/json");
if (!token.isEmpty()) b.header("Authorization", "Bearer " + token);
if (headers != null) headers.forEach(b::header);
b.method(method, body == null ? HttpRequest.BodyPublishers.noBody() : HttpRequest.BodyPublishers.ofString(M.writeValueAsString(body)));
JsonNode env = M.readTree(C.send(b.build(), HttpResponse.BodyHandlers.ofString()).body());
if (env.hasNonNull("error")) throw new RuntimeException(env.get("error").toString());
return env.get("data");
}
}
require "json"
require "net/http"
BASE = "https://api.skillsafe.ai/v1/app-api"
TOKEN = "paste-your-token-here" # from https://sponsor-promises.skillsafe.ai/tokens.html
def api(method, path, body = nil, headers = {})
uri = URI(BASE + path)
req = Net::HTTPGenericRequest.new(method, !body.nil?, true, uri.request_uri,
{ "Content-Type" => "application/json" }.merge(TOKEN.empty? ? {} : { "Authorization" => "Bearer #{TOKEN}" }).merge(headers))
req.body = JSON.generate(body) unless body.nil?
env = JSON.parse(Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |h| h.request(req) }.body)
raise env["error"].to_s if env["error"]
env["data"]
end
<?php
const BASE = "https://api.skillsafe.ai/v1/app-api";
$TOKEN = "paste-your-token-here"; // from https://sponsor-promises.skillsafe.ai/tokens.html
function api(string $method, string $path, $body = null, array $headers = []) {
global $TOKEN;
$h = ["Content-Type: application/json"];
if ($TOKEN) $h[] = "Authorization: Bearer $TOKEN";
foreach ($headers as $k => $v) $h[] = "$k: $v";
$ch = curl_init(BASE . $path);
curl_setopt_array($ch, [CURLOPT_CUSTOMREQUEST => $method, CURLOPT_HTTPHEADER => $h, CURLOPT_RETURNTRANSFER => true]);
if ($body !== null) curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
$env = json_decode(curl_exec($ch), true);
if (!empty($env["error"])) throw new Exception(json_encode($env["error"]));
return $env["data"];
}
// Program.cs -- .NET 6+ console app
using System.Net.Http.Json; using System.Text.Json; using System.Text.Json.Nodes;
static class Api {
public const string Base = "https://api.skillsafe.ai/v1/app-api";
public static string Token = "paste-your-token-here"; // from https://sponsor-promises.skillsafe.ai/tokens.html
static readonly HttpClient C = new();
public static async Task<JsonNode?> Call(string method, string path, object? body = null, Dictionary<string, string>? headers = null) {
var req = new HttpRequestMessage(new HttpMethod(method), Base + path);
if (Token != "") req.Headers.Add("Authorization", "Bearer " + Token);
if (headers != null) foreach (var h in headers) req.Headers.Add(h.Key, h.Value);
if (body != null) req.Content = JsonContent.Create(body);
var env = JsonNode.Parse(await (await C.SendAsync(req)).Content.ReadAsStringAsync())!;
if (env["error"] is JsonNode e && e.GetValueKind() != JsonValueKind.Null) throw new Exception(e.ToJsonString());
return env["data"];
}
}
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":"sponsor-promises"}' | jq -r '.data.token')
# a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN = ""
TOKEN = api("POST", "/guest", {"slug": "sponsor-promises"})["token"]
// a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN = "";
TOKEN = (await api("POST", "/guest", { slug: "sponsor-promises" })).token;
// inside main: a guest token (enough for /me and /estimate); a run needs your personal token
token = ""
g, err := api("POST", "/guest", map[string]string{"slug": "sponsor-promises"}, nil)
if err != nil { panic(err) }
token = g["token"].(string)
// inside main: a guest token (enough for /me and /estimate); a run needs your personal token
token = "";
token = api("POST", "/guest", Map.of("slug", "sponsor-promises"), null).get("token").asText();
# a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
TOKEN.replace("")
TOKEN.replace(api("POST", "/guest", { slug: "sponsor-promises" })["token"])
// a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
$TOKEN = "";
$TOKEN = api("POST", "/guest", ["slug" => "sponsor-promises"])["token"];
// a guest token (enough for /me and /estimate); a run needs your personal token from /tokens.html
Api.Token = "";
Api.Token = (await Api.Call("POST", "/guest", new { slug = "sponsor-promises" }))!["token"]!.GetValue<string>();
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}'
me = api("GET", "/me")
print(me["subject_type"], me.get("credits"))
const me = await api("GET", "/me");
console.log(me.subject_type, me.credits);
me, _ := api("GET", "/me", nil, nil)
fmt.Println(me["subject_type"], me["credits"])
JsonNode me = api("GET", "/me", null, null);
System.out.println(me.get("subject_type") + " " + me.get("credits"));
me = api("GET", "/me")
puts [me["subject_type"], me["credits"]].inspect
$me = api("GET", "/me");
echo $me["subject_type"], " ", $me["credits"] ?? "", "\n";
var me = await Api.Call("GET", "/me");
Console.WriteLine($"{me!["subject_type"]} {me["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": "status", "event": "Event: ...; 2027-05-12 to 2027-05-13; community-run; ...", "matrix": "The matrix, one column per sponsor ...", "facts": "Phase: pre; fulfillment clock: ..."}
# - see the input table
api POST /estimate "$(cat input.json)" | jq '.data | {hold_credits, min_credits, model, model_alias, markup_bps, warnings}'
inp = json.load(open("input.json")) # {"task": "status", "event": "Event: ...; 2027-05-12 to 2027-05-13; community-run; ...", "matrix": "The matrix, one column per sponsor ...", "facts": "Phase: pre; fulfillment clock: ..."}
# - see the input table
est = api("POST", "/estimate", inp)
print(est["hold_credits"], est["min_credits"], est["model"], est.get("warnings"))
import { readFileSync } from "node:fs";
const input = JSON.parse(readFileSync("input.json", "utf8")); // {task: "status" or "sponsor", event, matrix, facts} (see the input table)
const est = await api("POST", "/estimate", input);
console.log(est.hold_credits, est.min_credits, est.model, est.warnings);
raw, _ := os.ReadFile("input.json") // add "os" to the imports
var input map[string]any
json.Unmarshal(raw, &input)
est, _ := api("POST", "/estimate", input, nil)
fmt.Println(est["hold_credits"], est["min_credits"], est["model"])
Map<String, Object> input = M.readValue(new java.io.File("input.json"), Map.class);
JsonNode est = api("POST", "/estimate", input, null);
System.out.println(est.get("hold_credits") + " " + est.get("min_credits") + " " + est.get("model"));
input = JSON.parse(File.read("input.json"))
est = api("POST", "/estimate", input)
puts [est["hold_credits"], est["min_credits"], est["model"]].inspect
$input = json_decode(file_get_contents("input.json"), true);
$est = api("POST", "/estimate", $input);
echo $est["hold_credits"], " ", $est["min_credits"], " ", $est["model"], "\n";
var input = JsonNode.Parse(File.ReadAllText("input.json"))!;
var est = await Api.Call("POST", "/estimate", input);
Console.WriteLine($"{est!["hold_credits"]} {est["min_credits"]} {est["model"]}");
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 sponsor-promises:<task>:<inputHash>:a<attempt> - the lane is part of the key - and its one automatic reformat retry is a new attempt number, named in the page as one extra run. A status memo carries summary, clock, payment, sponsors, caps, leads, measurement, signals and caveats; a sponsor message carries mode, to, subject, body, held, misses and note. The code below prints the headline parts of either (list items are plain strings).
KEY="sponsor-promises:status:$(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 '.summary // .format, .note // .subject, ((.signals // .caveats)[] | "\(.signal // .caveat): \(.text // .text)")' reply.json
jq -r '.body // .note // empty' reply.json # the email to the sponsor (sponsor)
import hashlib, time
key = "sponsor-promises:" + inp["task"] + ":" + hashlib.sha256(json.dumps(inp).encode()).hexdigest()[:16] + ":a1"
job = api("POST", "/run", inp, {"Idempotency-Key": key})
while True:
j = api("GET", "/jobs/" + job["job_id"])
if j["status"] in ("succeeded", "failed", "cancelled"):
break
time.sleep(2)
reply = json.loads(j["output"]["output"]) # the reply as one JSON object
print(j["charged_credits"], j.get("truncated"), reply.get("summary"))
print(reply.get("note") or reply.get("subject", ""))
for s in reply.get("signals") or reply.get("caveats") or []:
print(s.get("signal", s.get("caveat")), "-", s.get("text", s.get("text")))
if reply.get("body"):
print("body:", reply["body"])
import { createHash } from "node:crypto";
const key = `sponsor-promises:${input.task}:${createHash("sha256").update(JSON.stringify(input)).digest("hex").slice(0, 16)}:a1`;
const job = await api("POST", "/run", input, { "Idempotency-Key": key });
let j;
do { await new Promise((r) => setTimeout(r, 2000)); j = await api("GET", "/jobs/" + job.job_id); }
while (!["succeeded", "failed", "cancelled"].includes(j.status));
const reply = JSON.parse(j.output.output);
console.log(j.charged_credits, j.truncated, reply.summary);
console.log(reply.note ?? reply.subject);
for (const s of reply.signals || reply.caveats || []) console.log(s.signal ?? s.caveat, "-", s.text ?? s.text);
if (reply.body) console.log("body:", reply.body);
sum := sha256.Sum256(raw) // add "crypto/sha256", "encoding/hex", "time" to the imports
key := "sponsor-promises:" + input["task"].(string) + ":" + hex.EncodeToString(sum[:8]) + ":a1"
job, _ := api("POST", "/run", input, map[string]string{"Idempotency-Key": key})
var j map[string]any
for {
time.Sleep(2 * time.Second)
j, _ = api("GET", "/jobs/"+job["job_id"].(string), nil, nil)
if s := j["status"]; s == "succeeded" || s == "failed" || s == "cancelled" { break }
}
var reply map[string]any
json.Unmarshal([]byte(j["output"].(map[string]any)["output"].(string)), &reply)
items, _ := reply["signals"].([]any) // signals and caveats are plain strings
fmt.Println(j["charged_credits"], j["truncated"], reply["summary"])
fmt.Println(reply["note"], reply["subject"])
for _, x := range items {
c := x.(map[string]any)
fmt.Println(c["signal"], "-", c["status"])
}
if fix, ok := reply["body"].(string); ok && fix != "" {
fmt.Println("body:", fix)
}
var digest = java.security.MessageDigest.getInstance("SHA-256").digest(M.writeValueAsBytes(input));
String key = "sponsor-promises:" + input.get("task") + ":" + HexFormat.of().formatHex(digest, 0, 8) + ":a1";
JsonNode job = api("POST", "/run", input, Map.of("Idempotency-Key", key)), j;
do { Thread.sleep(2000); j = api("GET", "/jobs/" + job.get("job_id").asText(), null, null); }
while (!Set.of("succeeded", "failed", "cancelled").contains(j.get("status").asText()));
JsonNode reply = M.readTree(j.get("output").get("output").asText());
System.out.println(j.get("charged_credits") + " " + reply.get("summary"));
System.out.println(reply.path("note").asText(reply.path("subject").asText()));
for (JsonNode s : reply.has("signals") ? reply.path("signals") : reply.path("caveats")) System.out.println(s.path("signal").asText(s.path("caveat").asText()) + " - " + s.path("status").asText(s.path("text").asText()));
if (!reply.path("body").asText().isEmpty()) System.out.println("body: " + reply.get("body").asText());
require "digest"
key = "sponsor-promises:#{input["task"]}:#{Digest::SHA256.hexdigest(JSON.generate(input))[0, 16]}:a1"
job = api("POST", "/run", input, { "Idempotency-Key" => key })
j = nil
loop do
sleep 2
j = api("GET", "/jobs/#{job["job_id"]}")
break if %w[succeeded failed cancelled].include?(j["status"])
end
reply = JSON.parse(j["output"]["output"])
puts [j["charged_credits"], j["truncated"], reply["summary"]].inspect
puts reply["note"] || reply["subject"]
(reply["signals"] || reply["caveats"] || []).each { |s| puts "#{s["signal"] || s["caveat"]} - #{s["text"] || s["text"]}" }
puts "body: #{reply["body"]}" unless reply["body"].to_s.empty?
$key = "sponsor-promises:" . $input["task"] . ":" . substr(hash("sha256", json_encode($input)), 0, 16) . ":a1";
$job = api("POST", "/run", $input, ["Idempotency-Key" => $key]);
do { sleep(2); $j = api("GET", "/jobs/" . $job["job_id"]); }
while (!in_array($j["status"], ["succeeded", "failed", "cancelled"]));
$reply = json_decode($j["output"]["output"], true);
echo $j["charged_credits"], " ", ($reply["summary"] ?? ""), "\n";
echo $reply["note"] ?? $reply["subject"] ?? "", "\n";
foreach ($reply["signals"] ?? $reply["caveats"] ?? [] as $s) echo $s["signal"] ?? $s["caveat"], " - ", $s["text"] ?? $s["text"], "\n";
if (!empty($reply["body"])) echo "body: ", $reply["body"], "\n";
var digest = System.Security.Cryptography.SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(input.ToJsonString()));
var key = $"sponsor-promises:{input["task"]}:{Convert.ToHexString(digest, 0, 8).ToLowerInvariant()}:a1";
var job = await Api.Call("POST", "/run", input, new() { ["Idempotency-Key"] = key });
JsonNode j;
do { await Task.Delay(2000); j = (await Api.Call("GET", "/jobs/" + job!["job_id"]))!; }
while (!new[] { "succeeded", "failed", "cancelled" }.Contains(j["status"]!.GetValue<string>()));
var reply = JsonNode.Parse(j["output"]!["output"]!.GetValue<string>());
Console.WriteLine($"{j["charged_credits"]} {reply!["summary"]}");
Console.WriteLine($"{reply["note"] ?? reply["subject"]}");
foreach (var s in (reply["signals"] ?? reply["caveats"]) as JsonArray ?? new JsonArray()) Console.WriteLine($"{s!["signal"] ?? s["caveat"]} - {s["text"] ?? s["text"]}");
if (reply["body"] is JsonNode fix && fix.GetValue<string>() != "") Console.WriteLine("body: " + fix);
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: sponsor-promises:status:$(shasum -a 256 input.json | cut -c1-16):a1" --data @input.json
rev = json.load(open("input.json")) # the same run input as input.json: {"task": "status", "event": "Event: ...; 2027-05-12 to 2027-05-13; community-run; ...", "matrix": "The matrix, one column per sponsor ...", "facts": "Phase: pre; fulfillment clock: ..."}
# - see the input table
req = urllib.request.Request(BASE + "/run-stream", method="POST", data=json.dumps(rev).encode(),
headers={"Content-Type": "application/json", "Authorization": "Bearer " + TOKEN,
"Idempotency-Key": "sponsor-promises:status:" + hashlib.sha256(json.dumps(rev).encode()).hexdigest()[:16] + ":a1"})
with urllib.request.urlopen(req) as r:
for line in r:
line = line.decode().strip()
if line.startswith("data:"):
print(line[5:].strip()[:200])
const rev = JSON.parse(readFileSync("input.json", "utf8"));
const r = await fetch(BASE + "/run-stream", { method: "POST", body: JSON.stringify(rev), headers: {
"Content-Type": "application/json", Authorization: "Bearer " + TOKEN,
"Idempotency-Key": `sponsor-promises:status:${createHash("sha256").update(JSON.stringify(rev)).digest("hex").slice(0, 16)}:a1` } });
const dec = new TextDecoder();
for await (const chunk of r.body) for (const line of dec.decode(chunk).split("\n"))
if (line.startsWith("data:")) console.log(line.slice(5).trim().slice(0, 200));
rraw, _ := os.ReadFile("input.json") // add "bufio", "strings" to the imports
rs := sha256.Sum256(rraw)
req, _ := http.NewRequest("POST", base+"/run-stream", bytes.NewReader(rraw))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+token)
req.Header.Set("Idempotency-Key", "sponsor-promises:status:"+hex.EncodeToString(rs[:8])+":a1")
res, _ := http.DefaultClient.Do(req)
sc := bufio.NewScanner(res.Body)
for sc.Scan() { if l := sc.Text(); strings.HasPrefix(l, "data:") { fmt.Println(l[5:]) } }
String rev = java.nio.file.Files.readString(java.nio.file.Path.of("input.json"));
var rd = java.security.MessageDigest.getInstance("SHA-256").digest(rev.getBytes());
var sreq = HttpRequest.newBuilder(URI.create(BASE + "/run-stream")).header("Content-Type", "application/json")
.header("Authorization", "Bearer " + token).header("Idempotency-Key", "sponsor-promises:status:" + HexFormat.of().formatHex(rd, 0, 8) + ":a1")
.POST(HttpRequest.BodyPublishers.ofString(rev)).build();
C.send(sreq, HttpResponse.BodyHandlers.ofLines()).body().filter(l -> l.startsWith("data:")).forEach(System.out::println);
rev = File.read("input.json")
uri = URI(BASE + "/run-stream")
req = Net::HTTP::Post.new(uri, "Content-Type" => "application/json", "Authorization" => "Bearer #{TOKEN}",
"Idempotency-Key" => "sponsor-promises:status:#{Digest::SHA256.hexdigest(rev)[0, 16]}:a1")
req.body = rev
Net::HTTP.start(uri.host, uri.port, use_ssl: true) do |h|
h.request(req) { |res| res.read_body { |chunk| chunk.each_line { |l| puts l if l.start_with?("data:") } } }
end
$rev = file_get_contents("input.json");
$ch = curl_init(BASE . "/run-stream");
curl_setopt_array($ch, [CURLOPT_POST => true, CURLOPT_POSTFIELDS => $rev, CURLOPT_HTTPHEADER => [
"Content-Type: application/json", "Authorization: Bearer $TOKEN",
"Idempotency-Key: sponsor-promises:status:" . substr(hash("sha256", $rev), 0, 16) . ":a1"],
CURLOPT_WRITEFUNCTION => function ($ch, $chunk) { foreach (explode("\n", $chunk) as $l) if (str_starts_with($l, "data:")) echo $l, "\n"; return strlen($chunk); }]);
curl_exec($ch);
var rev = File.ReadAllText("input.json");
var rd = System.Security.Cryptography.SHA256.HashData(System.Text.Encoding.UTF8.GetBytes(rev));
var sreq = new HttpRequestMessage(HttpMethod.Post, Api.Base + "/run-stream") { Content = new StringContent(rev, System.Text.Encoding.UTF8, "application/json") };
sreq.Headers.Add("Authorization", "Bearer " + Api.Token);
sreq.Headers.Add("Idempotency-Key", $"sponsor-promises:status:{Convert.ToHexString(rd, 0, 8).ToLowerInvariant()}:a1");
using var http = new HttpClient();
using var res = await http.SendAsync(sreq, HttpCompletionOption.ResponseHeadersRead);
using var rdr = new StreamReader(await res.Content.ReadAsStreamAsync());
for (string? l; (l = await rdr.ReadLineAsync()) != null;) if (l.StartsWith("data:")) Console.WriteLine(l);