← Sponsor Sizer / API
Tokens

Drive Sponsor Sizer from your own code

The page does its free work in the browser: it reads notes on one creator (platform, follower count, likes, comments and views per post, a media kit, a rate card, past sponsored captions) and notes on what you sell, computes the engagement rate and tier, sets a quote against the skill's starting range, grades the five vetting checks and the disclosure in past sponsored captions, lists the agreement terms still open and raises flags CD-01..CD-19. Its two paid lanes are available over HTTP. You send one JSON object with task set to "vet" or "brief", and the model replies with one JSON object. The easiest way to build the facts string is the page itself: Creatorkit.buildInput(lane, Creatorkit.analyze(creator, {brand, goal}), {vetHandoff}) in creatorkit.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
"vet"The vetting: the creator restated in plain language; a verdict (partner, test first or pass); the tier; audience fit against your buyer (strong, partial, weak or unknown) with quotes; the engagement read (healthy, low, suspicious or unknown); red flags with severity and quotes; the compensation model (flat, hybrid, performance, gifting, ambassador or ugc); the rate (quoted, the skill's starting range, an anchor, how to judge it on cost per outcome); the agreement terms (deliverables, usage rights, disclosure, and exclusivity when you list competitors); the tracking to set up; a 1:1 outreach opener; and what is missing.
"brief"The creative brief: the why in one sentence, two or three talking points each backed by a quote from what you sell, one CTA with the code and link (yours, or placeholders), guardrails, the written and spoken disclosure plus the platform label, deliverables, usage rights, tracking, creative freedom, the brief text to send (350 words or fewer) and what to check before sending.

Input fields (all strings)

fieldwhencontent
taskrequiredvet or brief
creatorrequiredWhat you know about the creator, verbatim. Past 9,000 characters the page cuts the middle on a line boundary and leaves a [sponsor-sizer: ...] marker.
factsrequiredA JSON string: summary, numbers (platform, handle, followers, tier, likes / comments / views with basis, engagement_rate, engagement_basis, stated_engagement_rate, view_rate, quoted_rate, budget, tier_range, rate_vs_range, cpm, cost_per_engagement), checks (id, status: met|unclear|not met, why, evidence), disclosure (line, verdict: clear|buried|insufficient|missing, why, quote), signals, brand (given, goal, proof, buyer, redlines, competitors, tracking), terms (id, found), flags (uid, id, sev, ref, name), notes. It is Creatorkit.factsOf(A).
brandoptionalWhat you sell: the product, the buyer, the goal, budget, proof, competitors, a promo code or landing page, redlines. Cut in the middle past 5,000 characters.
goaloptionalawareness, conversions, content or trust.
vet_handoffbrief onlyA JSON string of a vetting's verdict, tier, model{id}, deal_terms[{term, ask}], tracking[{type, detail}] and red_flags[{flag}], for the same notes.
retry_noteoptionalOnly on a reformat retry: what was wrong with the previous reply.

The reply contracts

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

task: "vet"

creator_plain{who, audience, numbers, price}, verdict (partner|test first|pass), verdict_why, tier (nano|micro|mid|macro|b2b), fit{level: strong|partial|weak|unknown, why, evidence[]}, engagement{read: healthy|low|suspicious|unknown, why, evidence[]}, red_flags[{flag, severity: high|medium|low, evidence[]}], model{id, why}, rate{quoted, range, anchor, basis}, deal_terms[{term: deliverables|usage_rights|exclusivity|approvals|disclosure|payment|kill, ask, why}], tracking[{type: code|utm|vanity|survey, detail}], opener, missing[{item, why, get}].

task: "brief"

source (vet handoff|from the input), model, why, talking_points[{point, proof}] (two or three), cta{action, code, link}, guardrails[], disclosure{written, spoken, label}, deliverables[{item, detail}], usage_rights, tracking[{type, detail}], creative_freedom, brief_text, before_sending[].

Worked examples

These are the page's own bundled examples (invented creators, brands and numbers), with the input as app.js builds it and the saved model reply the page replays for free.

Vetting: a micro hiking creator for a sock brand

Input (notes and facts shortened here):

{
 "task": "vet",
 "creator": "@rae.tindletrail - Rae Tindlebury, TikTok and Instagram Reels\nTikTok: 38,400 followers. Instagram: 11,200 followers.\nContent: weekend backpacking trips in the Cascades, gear tests after 50+ miles, budget trail food.\n\nLast 5 TikToks:\n- \"Testing three rain shells in a Washington downpour\" - 61,000 views, 4,900 likes, 312 comments\n- \"What I eat on a 3-day trip for under $25\" - 44,000 views, 3,700 likes, 268 comments\n- \"My boo... (1438 characters in all)",
 "facts": "(a JSON string; decoded: platform tiktok, followers 38400, tier micro, engagement rate 10.76, quoted rate 1200, checks engagement met; bots unclear; track met; safety met; fit unclear, disclosure clear, flags none)",
 "brand": "Brackenloom Sock Co. - merino hiking socks sold direct to consumers at brackenloom.example.com.\nOur buyers are new and intermediate hikers, mostly 22-40, who get blisters on their first long trips.\nGoal: conversions for our new Blister Guard sock.\nProof: 4.8 out of 5 stars from 2,140 reviews. In our 2025 field test, 37 of 40 testers finished a 3-day trip with no blisters.\nBudget: up to $2,000 for a first test.\nCompetitors: Da... (596 characters in all)",
 "goal": "conversions"
}

Reply:

{
 "task": "vet",
 "creator_plain": {
  "who": "@rae.tindletrail (Rae Tindlebury), TikTok and Instagram Reels",
  "audience": "58% women, 71% ages 22-34, 64% in the US Pacific Northwest; mostly new and intermediate backpackers, per her media kit",
  "numbers": "TikTok: 38,400 followers; Instagram: 11,200 followers. Last 5 TikToks ran from 39,500 to 61,000 views, 2,950 to 4,900 likes and 201 to 344 comments.",
  "price": "$1,200 per TikTok, $400 to add an Instagram Reel cross-post, usage rights for paid ads +30% per month"
 },
 "verdict": "partner",
 "verdict_why": "Her followers are the same new and intermediate hikers Brackenloom sells to, her engagement is far above the floor, and she already talks about blisters and socks. Start with one tracked hybrid deal on the Blister Guard sock.",
 "tier": "micro",
 "fit": {
  "level": "strong",
  "why": "Her media kit audience matches your buyer on experience level and age, and her own content and comments already cover blister care and socks.",
  "evidence": [
   "Followers are mostly new and intermediate backpackers",
   "Our buyers are new and intermediate hikers, mostly 22-40, who get blisters on their first long trips",
   "\"Blister care that actually works on trail\" - 47,800 views, 3,600 likes, 287 comments",
   "Which socks were you wearing on the 400 mile boots?"
  ]
 },
 "engagement": {
  "read": "healthy",
  "why": "The page computes 10.76% engagement on 38,400 followers, well above the rough 1-3% floor, with steady views across all five posts and no generic comments found.",
  "evidence": [
   "TikTok: 38,400 followers. Instagram: 11,200 followers",
   "\"Testing three rain shells in a Washington downpour\" - 61,000 views, 4,900 likes, 312 comments"
  ]
 },
 "red_flags": [
  {
   "flag": "The past campaign result is her own
... (shortened here; the page shows it whole)

Brief: the same creator, carrying the vetting

Input (with the vetting handed over):

{
 "task": "brief",
 "creator": "@rae.tindletrail - Rae Tindlebury, TikTok and Instagram Reels\nTikTok: 38,400 followers. Instagram: 11,200 followers.\nContent: weekend backpacking trips in the Cascades, gear tests after 50+ miles, budget trail food.\n\nLast 5 TikToks:\n- \"Testing three rain shells in a Washington downpour\" - 61,000 views, 4,900 likes, 312 comments\n- \"What I eat on a 3-day trip for under $25\" - 44,000 views, 3,700 likes, 268 comments\n- \"My boo... (1438 characters in all)",
 "facts": "(a JSON string; decoded: platform tiktok, followers 38400, tier micro, engagement rate 10.76, quoted rate 1200, checks engagement met; bots unclear; track met; safety met; fit unclear, disclosure clear, flags none)",
 "brand": "Brackenloom Sock Co. - merino hiking socks sold direct to consumers at brackenloom.example.com.\nOur buyers are new and intermediate hikers, mostly 22-40, who get blisters on their first long trips.\nGoal: conversions for our new Blister Guard sock.\nProof: 4.8 out of 5 stars from 2,140 reviews. In our 2025 field test, 37 of 40 testers finished a 3-day trip with no blisters.\nBudget: up to $2,000 for a first test.\nCompetitors: Da... (596 characters in all)",
 "goal": "conversions",
 "vet_handoff": "{\"verdict\":\"partner\",\"tier\":\"micro\",\"model\":{\"id\":\"hybrid\"},\"deal_terms\":[{\"term\":\"deliverables\",\"ask\":\"One TikTok on the Blister Guard sock, worn on a real trip, plus [optional Instagram Reel cross-post], live by [go-live date].\"},{\"term\":\"usage_rights\",\"ask\":\"Paid-ad whitelisting of the TikTok for [3-6 months] at her..."
}

Reply:

{
 "task": "brief",
 "source": "vet handoff",
 "model": "hybrid",
 "why": "New and intermediate backpackers get blisters on their first long trips, and Blister Guard is a merino hiking sock made for exactly those miles; your followers already ask which socks you wear.",
 "talking_points": [
  {
   "point": "Tested on real multi-day trips: most testers in Brackenloom's own field test finished a 3-day trip blister-free.",
   "proof": "In our 2025 field test, 37 of 40 testers finished a 3-day trip with no blisters."
  },
  {
   "point": "Hikers who bought Brackenloom socks rate them highly.",
   "proof": "4.8 out of 5 stars from 2,140 reviews"
  }
 ],
 "cta": {
  "action": "Try Blister Guard on your next trip: use code RAE15 at brackenloom.example.com/rae, also linked in bio.",
  "code": "RAE15",
  "link": "brackenloom.example.com/rae"
 },
 "guardrails": [
  "Do not say the socks prevent all blisters; say they helped in testing and on your trip.",
  "Do not compare Blister Guard to any named brand, including Screeknit or Fellwarden.",
  "Do not promise features or results beyond the field test and the review rating.",
  "Do not imply you have worn Brackenloom for years; describe only what you actually tested.",
  "Do not give medical advice on treating blisters as part of this post."
 ],
 "disclosure": {
  "written": "#ad as the very first word of the caption, in the first line, not in the hashtags or below the fold.",
  "spoken": "Ad: Brackenloom Sock Co. sent me these and paid for this video.",
  "label": "TikTok \"Paid partnership\" label switched on; Instagram \"Paid partnership\" label on the Reel if you cross-post."
 },
 "deliverables": [
  {
   "item": "One TikTok on the Blister Guard sock, worn on a real trip",
   "detail": "Your format and length, live by [go-live date]."
  },
  {
   "it
... (shortened here; the page shows it whole)

Vetting: a 412k account with 0.3% engagement

Input:

{
 "task": "vet",
 "creator": "@luxwren.daily - lifestyle and beauty, Instagram\n412,000 followers (gained 180,000 followers in two weeks in March).\nAverage likes: 1,300. Average comments: 40.\nMedia kit says engagement rate 6.2%.\n\nRecent sponsored caption:\n\"Obsessed with my glow routine lately, the serum from @glintmoss is everything. Link in bio! #sp #skincare #glow #beauty #selfcare #routine #glintmoss #morning\"\n\nSample comments on her last post:\n- \"n... (558 characters in all)",
 "facts": "(a JSON string; decoded: platform instagram, followers 412000, tier mid, engagement rate 0.33, quoted rate 9000, checks engagement not met; bots not met; track unclear; safety not met; fit unclear, disclosure insufficient, flags CD-01, CD-02, CD-09, CD-03, CD-07, CD-14, CD-11)",
 "brand": "Quellmira Skin - a fragrance-free moisturizer for sensitive skin, sold on our site and at two regional pharmacies.\nOur customers are 30-50 year old women with sensitive or rosacea-prone skin.\nGoal: awareness before a retail launch.\nProof: dermatologist-tested; 1,300 five-star reviews.\nBudget: $6,000.\nCompetitors: Glintmoss, Calvessa.",
 "goal": "awareness"
}

Reply:

{
 "task": "vet",
 "creator_plain": {
  "who": "@luxwren.daily on Instagram, lifestyle and beauty",
  "audience": "unknown",
  "numbers": "412,000 followers (gained 180,000 in two weeks in March); average likes 1,300, average comments 40; media kit states 6.2% engagement",
  "price": "$9,000 per feed post, usage rights not included, payment upfront"
 },
 "verdict": "pass",
 "verdict_why": "Engagement is 0.33% on 412,000 followers, with a 180,000-follower spike and generic comments that point to bought followers. She also just promoted Glintmoss, a competitor you listed.",
 "tier": "mid",
 "fit": {
  "level": "unknown",
  "why": "The notes give her niche (lifestyle and beauty) but nothing on who follows her, so there is no way to match her audience to 30-50 year old women with sensitive or rosacea-prone skin.",
  "evidence": []
 },
 "engagement": {
  "read": "suspicious",
  "why": "The page computes 0.33% engagement ((1,300 likes + 40 comments) / 412,000 followers), far under the rough 1% floor, alongside a follower spike and 5 generic comments.",
  "evidence": [
   "Average likes: 1,300. Average comments: 40.",
   "412,000 followers (gained 180,000 followers in two weeks in March)."
  ]
 },
 "red_flags": [
  {
   "flag": "Active competitor deal: her recent sponsored post promotes Glintmoss, which you list as a competitor.",
   "severity": "high",
   "evidence": [
    "the serum from @glintmoss is everything"
   ]
  },
  {
   "flag": "Follower spike that looks like bought followers.",
   "severity": "high",
   "evidence": [
    "gained 180,000 followers in two weeks in March"
   ]
  },
  {
   "flag": "Engagement of 0.33% is under the rough 1% floor for a mid-tier account.",
   "severity": "high",
   "evidence": [
    "Average likes: 1,300. Average comments: 40."
   ]
  },
  {
  
... (shortened here; the page shows it whole)

Brief: a podcast read with the deal already agreed

Input:

{
 "task": "brief",
 "creator": "\"Scrubs and Ledgers\" - a weekly podcast about personal finance for nurses, hosted by Dana Pellicorne, RN.\nDownloads per episode: 9,500 (her media kit, last 90 days). Mostly Apple Podcasts and Spotify.\nListeners are nurses and nursing students; she says 80% are women and most are in their first five years of practice.\nShe reads ads herself, mid-roll, about 60 seconds, and keeps a promo code per sponsor.\nPast sponsors inc... (530 characters in all)",
 "facts": "(a JSON string; decoded: platform podcast, followers 9500, tier nano, engagement rate None, quoted rate 650, checks engagement unclear; bots unclear; track unclear; safety unclear; fit unclear, disclosure no captions, flags CD-13, CD-16)",
 "brand": "Rotaplume - a budgeting app built for people paid by the shift: it plans around irregular hours, overtime and differentials.\nOur users are hospital nurses, paramedics and other shift workers.\nGoal: conversions (free 30-day trial, then $6.99 a month).\nProof: 4.6 stars from 3,900 App Store reviews. Users who connect their pay schedule save an average of $212 in their first three months (in-app data, 2025).\nDeal agreed ... (662 characters in all)",
 "goal": "conversions"
}

Reply:

{
 "task": "brief",
 "source": "from the input",
 "model": "flat",
 "why": "Nurses paid by the shift have irregular hours, overtime and differentials that break ordinary budgeting apps, and Rotaplume is built to plan around exactly that.",
 "talking_points": [
  {
   "point": "It is made for shift pay: it budgets around irregular hours, overtime and differentials instead of a fixed salary.",
   "proof": "it plans around irregular hours, overtime and differentials"
  },
  {
   "point": "Other users rate it highly in the App Store.",
   "proof": "4.6 stars from 3,900 App Store reviews"
  },
  {
   "point": "Listeners can try it before paying anything.",
   "proof": "free 30-day trial, then $6.99 a month"
  }
 ],
 "cta": {
  "action": "Go to rotaplume.test/nightshift and use code NIGHTSHIFT for an extra month free on top of the 30-day trial.",
  "code": "NIGHTSHIFT",
  "link": "rotaplume.test/nightshift"
 },
 "guardrails": [
  "Do not give financial or tax advice, and do not promise that listeners will save money.",
  "Do not promise features or results Rotaplume does not have.",
  "Do not imply you use Rotaplume yourself unless you actually do.",
  "Finance is a regulated category: any claim beyond the approved talking points goes past Rotaplume legal first."
 ],
 "disclosure": {
  "written": "Start the episode show notes with \"Ad: this episode is sponsored by Rotaplume\" in the first line, not in tags or below the fold.",
  "spoken": "This episode is sponsored by Rotaplume. Said at the start of the mid-roll, before any talking point.",
  "label": "none for this format"
 },
 "deliverables": [
  {
   "item": "Mid-roll host read, episode 1",
   "detail": "About 60 seconds, read by Dana, in an October episode, one round of review on her talking points."
  },
  {
   "item": "M
... (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 vetting, the tier agreeing with the page's follower count, "partner" only with a strong audience fit, healthy engagement and no high red flag, a pass when engagement is under 1% at 10,000 followers or more, the engagement read agreeing with the page's arithmetic, agreement terms covering deliverables, usage rights and disclosure (and exclusivity when competitors are listed), tracking set up, promo codes copied or left as placeholders, every quote in the notes word for word, and no invented figures; for a brief, two or three talking points each backed by a quote from the brand notes, a written disclosure with #ad or #sponsored, a spoken line for video and audio, the CTA's code and link copied or placeholders, at least two guardrails, the brief under 350 words with the disclosure in it, the vetting's model kept, and no invented figures. 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 notes 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://sponsor-sizer.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":"sponsor-sizer"}' | 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": "vet", "creator": "...", "brand": "...", "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 sponsor-sizer:<lane>:<inputHash>:a<attempt>. The job's output.output is the reply text; truncated: true means the balance cut it short.

KEY="sponsor-sizer:vet:$(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 (brief)

The same run as Server-Sent Events. brief.json is a brief input, with vet_handoff when it follows a vetting.

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