Bulk Match-and-Enrich
The customer brings their OWN list of identifiers (emails, phone numbers, and/or
social handles, extracted from a CSV / Excel / pasted list) and wants to know
which of them are creators in our corpus and pull the full profile on every
match. This skill drives the deliberate two-step contract: a FREE match_creators
pass that returns the match count and the exact credit cost, a mandatory human
cost-confirmation, then a paid enrich_matches pass that delivers the enriched
data (inline for small sets, as a downloadable file for large ones). For brand,
agency, and talent-ops teams reconciling a list against the creator graph. Pro
or pilot plan only.
Read first: ${CLAUDE_PLUGIN_ROOT}/shared/conventions.md (tool schemas, credit
prices, the conventions). This skill honors thrifty/thorough credit modes
(${CLAUDE_PLUGIN_ROOT}/shared/credit-modes.md) and the Freshness Gate
(${CLAUDE_PLUGIN_ROOT}/shared/freshness-gate.md). The two-step,
human-confirms-the-spend contract below is non-negotiable: enrichment spends
credits, so it never fires without an explicit human yes.
Inputs to collect
- The list (required) — a CSV, spreadsheet, or pasted block. Pull every
identifier into one flat array of strings: email addresses, phone numbers,
and/or social handles, mixed together. The server auto-classifies each item,
so you do NOT need to label them by type or split them into columns; just
extract the raw values. Strip obvious non-identifiers (header cells, blank
rows, "N/A").
- Minimum batch — you must submit at least 25 identifiers in one call.
The free match is bounded to a minimum batch so it cannot be used as a
single-target membership lookup. If the user's list is smaller than 25, say
so and ask them to combine lists or add more; do not pad it with junk.
- Maximum batch — up to 50,000 identifiers per call. For larger lists,
chunk into multiple match calls.
- Credit mode — default
thorough; thrifty on the standard triggers
(thrifty caps how many matches you enrich, e.g. "enrich only what $X covers").
Flow
Step 1 — Match (FREE). Call match_creators:
{ "identifiers": ["amy@example.com", "+1 415 555 0100", "@charli", "..."] }
Returns counts only (no per-identifier map, no profile data):
{ submitted, matched, unmatched, duplicates, estimated_credits, balance, preview_token, expires_at }. estimated_credits is 3 × matched. The
preview_token is short-lived (the charge window is roughly 15 minutes) and is
the only way to enrich this exact matched set without re-charging. If the plan
is not pro/pilot, the tool returns a refused upgrade envelope; surface that
honestly and stop.
Step 2 — Surface the cost and get a human yes (the spend gate). Do NOT call
enrich_matches automatically. Report back, plainly:
Of identifiers, are creators in our corpus
( not found, resolved to a creator already counted).
Enriching all costs credits
(~$<estimated_credits × 0.025>); 3 credits per match. Your balance is
. Want me to enrich all ? (Or tell me a budget and I'll
enrich what it covers.)
Wait for an explicit confirmation. The confirmed_credit_amount you pass next
MUST equal the token's estimated_credits and MUST come from this human yes,
never be echoed automatically from the match result. That is the cost gate by
design.
Step 3 — Enrich (PAID, partial-to-balance, idempotent). After the yes, call
enrich_matches:
{
"preview_token": "<from step 1>",
"confirmed_credit_amount": <estimated_credits>,
"format": "csv"
}
- Cost: 3 credits per enriched match, charged exactly once on the first
call (a retried first call re-reads without re-charging).
- Partial-to-balance: if the balance cannot cover every match, the
affordable prefix is enriched and
unfunded reports how many remain. Tell
the user "enriched , still to go — top up and re-run the
same list to enrich the rest."
- Delivery: a funded set over ~200 rows auto-delivers as a downloadable
file (
format: csv | json | jsonl) via a short-lived signed URL that
expires in roughly 24 hours; smaller sets come back inline in pages of ~100.
Page large inline results with cursor — paging an already-charged token is
free. Default to format: "csv" for any sizeable run so the user gets one
clean file.
- Returns
{ enriched[], page_info:{next_cursor?}, file?, charged_credits, funded, unfunded, remaining_balance }. Each enriched row carries the full
profile surface: profile, deal signals, brand affiliations, avatar, and
account-level content stats, honoring the same per-field opt-out and
hidden-profile suppression as get_creator_profile.
Step 4 — Freshness Gate + assemble the deliverable. Apply the Freshness
Gate to the enriched rows (flag stale records for re-verify) and hand back the
file link (or the inline table) with the summary below.
Deliverable
# Bulk Match-and-Enrich — <list name>
_Creatorland Data · <date>_
**Match:** <submitted> submitted · **<matched> matched** · <unmatched> not in
corpus · <duplicates> duplicate-resolved.
**Enriched:** <funded> of <matched> (<unfunded> awaiting top-up).
**Spend:** <charged_credits> credits (~$<charged_credits × 0.025>) · balance now
<remaining_balance>.
**Your enriched data:** <signed-URL file link, expires ~24h>
<or, for small sets, the inline table:>
| Creator | Interests | Audience geo (top) | Affiliations (corpus) | Content stats | Freshness |
|---|---|---|---|---|---|
| <row…> | … | … | <brands / "unavailable on plan" / "none in corpus"> | … | fresh / aging / ⚠ stale |
## Notes
- Matching was free; you were charged only for the <funded> enriched matches.
- Affiliations are corpus-derived, not exhaustive — absence ≠ no relationships.
- The file link expires in ~24 hours; re-run the enrich step (paging the same
token is free) if you need it again within the window.
- <If unfunded > 0:> Top up <unfunded × 3> credits and re-run the same list to
enrich the remaining <unfunded>.
---
Data freshness: <F>/<funded> enriched rows synced within the last sync window;
<K> flagged for re-verification.
Provenance: Creatorland Data MCP · bulk match-and-enrich · <date>.
Credits used this run: <charged_credits> (<funded> matches × 3).
Honesty rules
- Match is free; enrich spends — and the human confirms the spend. Always
surface the matched count and the exact credit cost from step 1 BEFORE
enriching, and only call
enrich_matches after an explicit human yes. Never
auto-chain match → enrich.
confirmed_credit_amount is the gate, not a formality. It must equal the
token's estimated_credits and come from the human confirmation. Do not
fabricate or auto-echo it.
- Partial-to-balance is stated, never silent. When the balance funds only a
prefix, say exactly how many were enriched and how many remain, and that a
top-up + re-run finishes the rest.
- Minimum batch of 25. If the list is too small, say why (anti-probing
floor) rather than working around it.
- PII invariant (convention 7). The enriched surface is profile data,
affiliations, and account-level stats — never contact information. The MCP
returns no emails/phones/contact links and you surface none, even though the
user's OWN uploaded list contains identifiers. Do not echo the raw uploaded
identifiers back as if they were enrichment output.
- Plan honesty. Pro/pilot only; if the tool refuses for plan reasons,
relay the upgrade path plainly and stop. If affiliations are pro-gated and
absent on a row, mark "unavailable on plan", never blank-implying-clean.
- Freshness is a column AND a caveat. Stale enriched rows are flagged for
re-verification before they are used to pitch.
Credit footprint
thorough: matching is free; enriching is 3 credits per matched creator
(estimated_credits from step 1 is the whole cost, surfaced before you spend) ·
thrifty: enrich only what a user-stated budget covers (fund a prefix, report the
rest as awaiting top-up). The cost is always shown and confirmed before any
charge — it is the core contract of this skill, not an optional estimate.
1---2name: bulk-match-enrich3description: Take your OWN list of contacts (emails, phones, social handles from a CSV, Excel, or pasted list) and find which are creators in the Creatorland corpus, see the cost for free, confirm, then enrich every match. Use when the user says "match my list against your creators", "which of my contacts are creators", "bulk match and enrich", or "enrich this list of emails/handles". Match is free; enrichment is 3 credits per matched creator.4---56# Bulk Match-and-Enrich78The customer brings their OWN list of identifiers (emails, phone numbers, and/or9social handles, extracted from a CSV / Excel / pasted list) and wants to know10which of them are creators in our corpus and pull the full profile on every11match. This skill drives the deliberate two-step contract: a FREE `match_creators`12pass that returns the match count and the exact credit cost, a mandatory human13cost-confirmation, then a paid `enrich_matches` pass that delivers the enriched14data (inline for small sets, as a downloadable file for large ones). For brand,15agency, and talent-ops teams reconciling a list against the creator graph. Pro16or pilot plan only.1718Read first: ${CLAUDE_PLUGIN_ROOT}/shared/conventions.md (tool schemas, credit19prices, the conventions). This skill honors thrifty/thorough credit modes20(${CLAUDE_PLUGIN_ROOT}/shared/credit-modes.md) and the Freshness Gate21(${CLAUDE_PLUGIN_ROOT}/shared/freshness-gate.md). The two-step,22human-confirms-the-spend contract below is non-negotiable: enrichment spends23credits, so it never fires without an explicit human yes.2425## Inputs to collect2627- **The list** (required) — a CSV, spreadsheet, or pasted block. Pull every28 identifier into one flat array of strings: email addresses, phone numbers,29 and/or social handles, mixed together. The server auto-classifies each item,30 so you do NOT need to label them by type or split them into columns; just31 extract the raw values. Strip obvious non-identifiers (header cells, blank32 rows, "N/A").33- **Minimum batch** — you must submit at least **25 identifiers** in one call.34 The free match is bounded to a minimum batch so it cannot be used as a35 single-target membership lookup. If the user's list is smaller than 25, say36 so and ask them to combine lists or add more; do not pad it with junk.37- **Maximum batch** — up to 50,000 identifiers per call. For larger lists,38 chunk into multiple match calls.39- **Credit mode** — default `thorough`; `thrifty` on the standard triggers40 (thrifty caps how many matches you enrich, e.g. "enrich only what $X covers").4142## Flow4344**Step 1 — Match (FREE).** Call `match_creators`:4546```json47{ "identifiers": ["amy@example.com", "+1 415 555 0100", "@charli", "..."] }48```4950Returns counts only (no per-identifier map, no profile data):51`{ submitted, matched, unmatched, duplicates, estimated_credits, balance,52preview_token, expires_at }`. `estimated_credits` is `3 × matched`. The53`preview_token` is short-lived (the charge window is roughly 15 minutes) and is54the only way to enrich this exact matched set without re-charging. If the plan55is not pro/pilot, the tool returns a refused upgrade envelope; surface that56honestly and stop.5758**Step 2 — Surface the cost and get a human yes (the spend gate).** Do NOT call59`enrich_matches` automatically. Report back, plainly:6061> Of <submitted> identifiers, <matched> are creators in our corpus62> (<unmatched> not found, <duplicates> resolved to a creator already counted).63> Enriching all <matched> costs <estimated_credits> credits64> (~$<estimated_credits × 0.025>); 3 credits per match. Your balance is65> <balance>. Want me to enrich all <matched>? (Or tell me a budget and I'll66> enrich what it covers.)6768Wait for an explicit confirmation. The `confirmed_credit_amount` you pass next69MUST equal the token's `estimated_credits` and MUST come from this human yes,70never be echoed automatically from the match result. That is the cost gate by71design.7273**Step 3 — Enrich (PAID, partial-to-balance, idempotent).** After the yes, call74`enrich_matches`:7576```json77{78 "preview_token": "<from step 1>",79 "confirmed_credit_amount": <estimated_credits>,80 "format": "csv"81}82```8384- **Cost:** 3 credits per enriched match, charged exactly once on the first85 call (a retried first call re-reads without re-charging).86- **Partial-to-balance:** if the balance cannot cover every match, the87 affordable prefix is enriched and `unfunded` reports how many remain. Tell88 the user "enriched <funded>, <unfunded> still to go — top up and re-run the89 same list to enrich the rest."90- **Delivery:** a funded set over ~200 rows auto-delivers as a downloadable91 file (`format`: `csv` | `json` | `jsonl`) via a short-lived signed URL that92 expires in roughly 24 hours; smaller sets come back inline in pages of ~100.93 Page large inline results with `cursor` — paging an already-charged token is94 free. Default to `format: "csv"` for any sizeable run so the user gets one95 clean file.96- Returns `{ enriched[], page_info:{next_cursor?}, file?, charged_credits,97 funded, unfunded, remaining_balance }`. Each enriched row carries the full98 profile surface: profile, deal signals, brand affiliations, avatar, and99 account-level content stats, honoring the same per-field opt-out and100 hidden-profile suppression as `get_creator_profile`.101102**Step 4 — Freshness Gate + assemble the deliverable.** Apply the Freshness103Gate to the enriched rows (flag stale records for re-verify) and hand back the104file link (or the inline table) with the summary below.105106## Deliverable107108```markdown109# Bulk Match-and-Enrich — <list name>110_Creatorland Data · <date>_111112**Match:** <submitted> submitted · **<matched> matched** · <unmatched> not in113corpus · <duplicates> duplicate-resolved.114**Enriched:** <funded> of <matched> (<unfunded> awaiting top-up).115**Spend:** <charged_credits> credits (~$<charged_credits × 0.025>) · balance now116<remaining_balance>.117118**Your enriched data:** <signed-URL file link, expires ~24h>119<or, for small sets, the inline table:>120121| Creator | Interests | Audience geo (top) | Affiliations (corpus) | Content stats | Freshness |122|---|---|---|---|---|---|123| <row…> | … | … | <brands / "unavailable on plan" / "none in corpus"> | … | fresh / aging / ⚠ stale |124125## Notes126- Matching was free; you were charged only for the <funded> enriched matches.127- Affiliations are corpus-derived, not exhaustive — absence ≠ no relationships.128- The file link expires in ~24 hours; re-run the enrich step (paging the same129 token is free) if you need it again within the window.130- <If unfunded > 0:> Top up <unfunded × 3> credits and re-run the same list to131 enrich the remaining <unfunded>.132133---134Data freshness: <F>/<funded> enriched rows synced within the last sync window;135<K> flagged for re-verification.136Provenance: Creatorland Data MCP · bulk match-and-enrich · <date>.137Credits used this run: <charged_credits> (<funded> matches × 3).138```139140## Honesty rules141142- **Match is free; enrich spends — and the human confirms the spend.** Always143 surface the matched count and the exact credit cost from step 1 BEFORE144 enriching, and only call `enrich_matches` after an explicit human yes. Never145 auto-chain match → enrich.146- **`confirmed_credit_amount` is the gate, not a formality.** It must equal the147 token's `estimated_credits` and come from the human confirmation. Do not148 fabricate or auto-echo it.149- **Partial-to-balance is stated, never silent.** When the balance funds only a150 prefix, say exactly how many were enriched and how many remain, and that a151 top-up + re-run finishes the rest.152- **Minimum batch of 25.** If the list is too small, say why (anti-probing153 floor) rather than working around it.154- **PII invariant (convention 7).** The enriched surface is profile data,155 affiliations, and account-level stats — never contact information. The MCP156 returns no emails/phones/contact links and you surface none, even though the157 user's OWN uploaded list contains identifiers. Do not echo the raw uploaded158 identifiers back as if they were enrichment output.159- **Plan honesty.** Pro/pilot only; if the tool refuses for plan reasons,160 relay the upgrade path plainly and stop. If affiliations are pro-gated and161 absent on a row, mark "unavailable on plan", never blank-implying-clean.162- **Freshness is a column AND a caveat.** Stale enriched rows are flagged for163 re-verification before they are used to pitch.164165## Credit footprint166167thorough: matching is free; enriching is 3 credits per matched creator168(`estimated_credits` from step 1 is the whole cost, surfaced before you spend) ·169thrifty: enrich only what a user-stated budget covers (fund a prefix, report the170rest as awaiting top-up). The cost is always shown and confirmed before any171charge — it is the core contract of this skill, not an optional estimate.