MCP App Store
by KeenEthics
Business & Operations
webfaCeMEdia icon

webfaCeMEdia

by webfaCeMEdia

Overview

webfaCeMEdia connects your AI assistant to the webfaCeMEdia platform so you can manage your sites, contacts, content drafts, campaigns, and analytics in plain language. Each request is scoped to your own organization and runs against live platform data; destructive actions are clearly flagged before they run.

Tools

add_contact

ChatGPT
Add a single contact to a client's CRM. Useful for quickly adding prospects found via Apollo or referral without going through the sheet/Notion sync.

add_page_module

ChatGPT
Insert a new module (section) into a page. Module must be a complete object with _type and _key per SanityPress schema. Check the module catalog for the correct shape.

answer_my_ad_change

ChatGPT
Answer a change waiting for the owner's yes (get_my_ads → waitingForYou): e.g. more daily budget for a campaign that brings leads cheaply, or switching one back on. Tell the owner what changes and why; approve only after their yes (ownerConfirmed: true — the platform refuses an approval without it). Declining needs no confirmation. status 'error' means nothing changed: tell the owner the message, never report success; status 'approved_not_started' means it was approved but could not take effect.

append_to_array

ChatGPT
Append items to an array field on a Sanity document. Without insertAfter, items are appended at the end (and the array is created via setIfMissing if missing — single transaction). With insertAfter, items are inserted directly after the matching _key. Each item should include its own _key if Sanity's schema expects one; patch_document auto-generates _keys for items missing them. Common uses: adding a CTA to a hero, a stat to a stat-list, or a module to a page.

approve_my_ad_campaign

ChatGPT
The owner approves a campaign webfaCeMEdia sent for approval (status 'Waiting for your approval' in get_my_ads). Only the account owner or a Manager can approve. Approving STARTS it and spends the business's money, within the ad account's monthly limit. First show the owner the review link (it has the ads as they will look), the daily budget and where it runs; only after they say yes, call with ownerConfirmed: true (the platform refuses an approval without it). Returns whether it started: status 'approved_not_started' means it was approved but could not start (e.g. over the monthly limit — webfaCeMEdia is told); say so using message. status 'error' means nothing changed: tell the owner the message, never report success.

approve_preview_set

ChatGPT
Release a held design-preview SET (pending_approval → approved) WITHOUT emailing the client — the public preview link only renders approved/sent sets. Token-based, so it also works on an orphaned set that was generated but never attached to the project: pass setToken from list_preview_sets and the set is attached as part of the approval (it becomes the project's canonical preview unless a different set is kept). Omit setToken to approve the project's canonical set, else its newest. Optional visibleBundleIds cherry-picks the set's completed variants (max 3). Idempotent. Returns { ok, status:'approved', setToken, previewUrl, visibleCount, canonical }. not_enabled if the operator API is unset.

ask_for_ads

ChatGPT
Ask webfaCeMEdia for a new campaign or a change ("promote the fall special", "try a video with this clip", "spend more on Google", "switch the paused one back on"). Nothing goes live from here. With a full brief in plan (goal, offer, landing page, audience, places, daily budget, platforms) a campaign is prepared, checked by webfaCeMEdia and sent back for the owner's approval; otherwise the request is passed on. Always write request in the owner's words.

batch_create_projects

ChatGPT
Operator-only (admin). Generate sites from a prefilled LIST of redesign requirements — one project per row, each building + producing a design-preview SET (and emailing it when sendEmail + recipientEmail). Each row: { name, domain, sourceUrl?, industry?, leadGoal?, leadBrandVibe?, leadReferences?, leadAudience?, requireApproval?, recipientEmail? }. Pass ownerUserId (+ clerkOrgId/ownerOrgSlug) to run a partner's list under THEIR account/org (hybrid ownership: they manage it, you still see it); omit ownerUserId for operator-owned. When ownerUserId is set, that owner's Solo/Agency capability + bulk cap are enforced. Returns { created, results:[{ projectId, name, ok, error? }] }. Compose with the user's own Notion/Sheets connector to build the rows. Returns not_enabled if operatorBaseUrl/operatorApiSecret are unset.

begin_upload_url

ChatGPT
Start a direct upload for a large file (up to 25 MB; video 50 MB) when you can make HTTP requests yourself: returns a one-hour putUrl. POST the raw bytes to it with the file's Content-Type; the response is { storageId }. Then call finish_upload with the uploadId and storageId to get the media-library asset. If you cannot make HTTP requests, use upload_media's chunked mode instead.

create_document

ChatGPT
CREATE a new Sanity document. Fails with a clear error if the _id already exists (unlike upsert_document which replaces). Use this when you want create-or-fail semantics — adding a new portfolio entry, testimonial, blog post, etc. without risk of overwriting.

create_project

ChatGPT
Create a planner project. With build:'full' it runs the SAME question-driven build the conversational planner agent does — from the brief below — and returns a COMPLETE project the owner can open in the builder, redesign in Lab, or deploy. Gather as much of the brief as you can (ask the user the question in each field's description when unknown); only name + domain are required and the build degrades gracefully without the rest. build:'full' is async + a real premium run (minutes) — poll get_project_status until built. generatePreview:true also makes a 3-variant redesign preview SET (held for review — NO client email is sent). build:'draft' (default) just creates an empty project. Returns { projectId } or { projectId, building:true }. not_enabled if operatorBaseUrl/operatorApiSecret are unset.

create_social_draft

ChatGPT
Create a social post DRAFT for one or more platforms. Write platform-native copy per platform — not one caption pasted everywhere: a hook in the first line; X ≤ 280 chars; LinkedIn professional, 1–3 short paragraphs; Instagram/TikTok casual with line breaks and 3–5 hashtags at the end; Facebook conversational. Ground it in the business's real services, offers, hours and voice (get_client_details, the company profile, and the owner's brief); never invent prices or claims, never mention AI or that it was generated. Vary formats across a week (tip, behind-the-scenes, customer story, offer, question, seasonal) and check list_social_posts first so you do not repeat a recent angle. Instagram and TikTok REQUIRE an image or video: make one with generate_asset (assetType social) and pass its imageUrl in assets, upload one you have with upload_media and pass its asset, or reuse a library file from list_media_assets. A PDF/PPT/DOC (type document) publishes as a native LinkedIn document post — LinkedIn-only, one document, no other media; the first line of the LinkedIn caption becomes the document title. scheduledAt is a proposal only — nothing publishes until schedule_social_post is called after the owner approves. Times are ISO 8601 with the business's timezone offset (e.g. 2026-09-01T10:00:00-04:00).

decline_my_ad_campaign

ChatGPT
The owner (or a Manager) says no to a campaign waiting for approval. Pass their reason or what they'd like instead; webfaCeMEdia is told and nothing runs.

delete_document

ChatGPT
DELETE a Sanity document by _id. Destructive — only restorable via Sanity's revision history within the retention window. Requires confirmDelete: true.

delete_social_draft

ChatGPT
Delete a draft, approved or failed social post. Scheduled and published posts are refused — those are handled in the dashboard. Confirm with the owner before deleting something they wrote or approved.

find_client_by_domain

ChatGPT
Which client a domain (or an email sender's address) belongs to, matched against the client portfolio's site domain (www-insensitive; subdomains and agent domains also match). webfaCeMEdia's operator account searches every client; any other account searches only its own. Returns { domain, scope, found, client: null | { slug, displayName, siteDomain, agentDomain, type: 'full'|'site-only', status: 'active'|'inactive' }, matchedBy: 'exact'|'subdomain'|'agent_domain', deploymentHealth: null | { status: 'up'|'down'|'degraded', checkedAt, httpStatus, latencyMs, error } (latest 15-minute uptime probe) }.

finish_upload

ChatGPT
Complete an upload started with begin_upload_url (pass the storageId the putUrl POST returned) — or, for a chunked upload_media whose last part call failed, retry the finish with just the uploadId. Returns the permanent public url and a ready asset for the social drafts.

generate_asset

ChatGPT
Generate an image, logo, icon, or illustration for a client via Creative Studio. Optionally uploads to Sanity. Best for: hero images, service cards, blog covers, favicons, social post imagery.

generate_preview_set

ChatGPT
Generate the 3-variant design-preview SET for a planner project page — mixed variantModels, a distinct taste pack + palette + reference per variant, all behind ONE preview token — the same engine the redesign intake uses. ALWAYS call with dryRun:true FIRST: it returns the exact per-slot plan (provider, modelId, tastePackIdentifier, paletteOverride, referenceOverride) with a cost estimate per slot and totals (USD, images, lab credits) WITHOUT generating; show it to the user, then call again passing rerun.variants + rerun.variantModels back to run exactly what was quoted (un-pinned runs re-salt the ranker). BRAND GATE: if the project's colours are still the stock placeholder or a curated library palette (i.e. nobody chose them), the call returns { ok:false, reason:'brand_placeholder', matchedPalette, currentBranding, completedBundles, suggestion } and generates nothing — pass branding:{primaryColor, accentColor, …} (same shape as update_project_branding) to set the real brand in the same call, or allowPlaceholderBrand:true to proceed anyway. When the project already has completed designs, prefer update_project_branding → reskin_bundle (free) over regenerating. Other body: projectId (required), pageKey (defaults to the homepage), variantModels (1–3 of 'anthropic' (Claude Opus) | 'zai' (GLM) | 'grok' | 'openai' (GPT-5.6 Sol) | 'gemini'), variants[] (per-slot pins from list_taste_packs), requireApproval, userId. Real run returns { ok:true, setToken, bundleIds, previewUrl, pageKey, status, canonical, keptSetToken } — the project's canonical link only moves when no set is kept (see keep_preview_set); poll list_lab_bundles until each bundle is 'completed'. not_enabled if operatorBaseUrl / operatorApiSecret are unset.

get_agent_stats

ChatGPT
Return contact count, pending drafts, recent runs, and AI config for a client's agent.

get_analytics_site

ChatGPT
Return one Insights site's metadata, last 30 days of daily rollups, and last 100 raw events for debug.

get_brand_guide

ChatGPT
READ how a project's brand guide is built: the live branding fields (all colors incl. dark/footer, fonts, wordmark, logo URLs, theme), the full curated palette library (28 palettes × 14 industry kinds), and the Lab taste-pack vocabulary (palette archetypes + references with fit tags). Use it to author a brand block for create_project or targeted update_project_branding edits. Read-only.

get_chat_history_by_email

ChatGPT
Website chat conversations with a visitor who gave this email address (typed it in the chat, submitted it in a chat form, or it was captured by the chat's lead form), newest first, up to 5. Scoped to your own sites (webfaCeMEdia's operator account sees every site on the platform). Returns { email, scope, found, totalMatches, chats: [{ sessionId, siteId, siteHost, startedAt, lastMessageAt (ISO), summary (the stored AI summary, else the visitor's first message), summarySource, messageCount, matchedBy, transcriptUrl (null: no per-conversation link yet) }] }.

get_client_details

ChatGPT
Get detailed information for a single client including config, contact count, and recent agent runs.

get_contact_by_email

ChatGPT
Look up ONE CRM contact by email address (case-insensitive) — the CRM card for an email sender. Returns { found, contact: null | { id, name, firstName, lastName, company, email, status, source, lastContactDate, nextStep, nextStepAt, notes (last 500 chars), starred, staleScore, engagement: { score, lastOpened, lastClicked, unsubscribed } }, recentReplies: last 5 inbound campaign replies { id, from, subject, snippet, receivedAt } }. Use contact.id with update_contact.

get_deployment_health

ChatGPT
Fleet-level health summary across all client deployments. Each entry separates LIVENESS from HEALTH: reachable is the endpoint ping; agentHealthy is derived from the agent's runs (NOT the ping) — a deployment whose syncs complete is healthy even if unreachable. online is a back-compat alias of reachable. Counts (contacts, lastRunAt) come from the same source as get_agent_stats. CRITICAL for unattended use: read statsSource before trusting counts — 'live' = fresh, 'cache' = last-known (also stale:true), 'unavailable' = unknown (contacts is null, NEVER 0 — do not treat as zero). summary buckets: healthy (reachable + agentHealthy), unreachable (syncing but ping failed), failing (agentHealthy=false ONLY), unknown (stats unresolved), siteOnly. Each entry has kind: 'full' | 'site-only'; site-only deployments (no Convex agent) are pinged via their site URL and counted in summary.siteOnly, never failing.

get_document

ChatGPT
Fetch a single Sanity document by _id, regardless of type. Returns the full document JSON with image references preserved as _ref strings (not dereferenced URLs) so they can be reused in patch_document.

get_document_at_revision

ChatGPT
Fetch a point-in-time SNAPSHOT of a Sanity document at a given revision (from list_document_history) or ISO time. Returns the document as it existed then. Returns 'no_history_in_range' when outside the retention window. Read-only — does not modify anything.

get_my_ads

ChatGPT
The business's Facebook, Instagram and Google ads at a glance: its ad accounts (spent this month, monthly limit), each campaign and its status (running, paused, waiting for your approval — with the review link), changes waiting for the owner's yes, and how many campaigns webfaCeMEdia is preparing. Start here for any ads question.

get_my_ads_results

ChatGPT
How the ads are doing over the last N days (default 30): spend, impressions, clicks, leads and cost per lead, compared with the period before, per platform and per campaign. Numbers refresh every hour. Explain them plainly; pair with get_my_website_leads.

get_my_website_leads

ChatGPT
The enquiries the business's own website recorded over the last N days (default 30), split into from Google ads / from Facebook-Instagram ads / other. The honest count: ad platforms claim leads generously, this is what actually arrived.

get_navigation

ChatGPT
Fetch header, footer, and social navigation for a client via site singleton references. Read-only.

get_page

ChatGPT
Fetch a single page's full module content by slug or id. Read-only.

get_project_content

ChatGPT
Read a project's BUILT homepage content so you can QC the build against the prospect's real offering BEFORE sending — the preview link is held for approval, so this is the way to inspect output programmatically. Returns { businessName, industry, brand, brief:{industry,offerings,differentiator,goal}, homepage:{ slug, title, modules:[{type,heading,subheading,items[]}] }, pages:[{slug,title,moduleTypes[]}] }. Compare homepage against brief (and the prospect's real site): does the hero lead with their actual offering? Are the services in the right order? Did a stale template positioning leak in? Owner-scoped on the public connector. not_enabled if the operator API is unset.

get_project_status

ChatGPT
Poll a project's build + preview status — use after create_project build:'full' or batch_create_projects to know when the build is done and to get the shareable preview link. Returns { buildStatus, buildError, hasPreview, previewUrl, previewStatus, sentTo, variants:[{bundleId,status}] }. The build is complete when buildStatus is 'generated' (or hasPreview is true); then open previewUrl to review the redesign before sending. Owner-scoped on the public connector. not_enabled if the operator API is unset.

get_schema

ChatGPT
Inspect a site's content schema BEFORE writing. With { client }, returns that client's actually-DEPLOYED Sanity schema (source: 'server') or the bundled template (source: 'template-fallback') if none is deployed — field support differs from site to site (e.g. some sites have i18n fields, different module sets). With { client, type }, returns that type's allowed fields and which are multilingual (i18nFields). Without { client }, returns the generic template baseline (advisory only). Use this to learn valid fields before create_document / patch_document so writes aren't rejected by the schema gate.

get_singleton

ChatGPT
Generic singleton fetcher for whitelisted document IDs (site, pricing, shop-settings, etc.). Read-only.

get_site_settings

ChatGPT
Fetch the site singleton (title, blurb, logo, announcements, CTAs, copyright) for a client. Read-only.

get_social_post

ChatGPT
Read one social post in full (captions, assets, status, schedule, publish results) by postId.

go_live_project

ChatGPT
Move a client site to its production domain. Routes by client: webface.cloud apps (wfcAppId) → platform attach_domain; planner-built Vercel sites (projectId / plannerProjectId) → operator go-live (Vercel domain + NEXT_PUBLIC_BASE_URL + Sanity CORS + planner doc + portfolio + Insights + Clerk + redeploy); otherwise Insights /setSiteDomain + platform portfolio siteDomain only. Returns per-target {ok,error} rows, the DNS records to create, and nextSteps. Never rolls back partial success.

keep_preview_set

ChatGPT
Keep a design-preview SET: pin the project's canonical preview link to it and stop later generate_preview_set calls from displacing it (new sets then land as 'latest' and stay reachable via list_preview_sets). Use it the moment a set is good so a regeneration never loses it. Keeping does NOT change approval status — pass approve:true to also release a held set (no email), or call approve_preview_set. Optional label (e.g. 'client liked v2 layout'). Returns { ok, setToken, previewUrl, label, status, pageKey }. not_enabled if the operator API is unset.

list_analytics_events

ChatGPT
Paginated raw event log for one site (debug / verification). Pass dayBucket (UTC ISO date) to scope.

list_analytics_sites

ChatGPT
List every site registered in the webfaCeMEdia Insights Convex deployment, with last-7-day pageview/visitor counts and archive status.

list_brand_palettes

ChatGPT
The curated brand-palette library (28 hand-picked, WCAG-checked palettes grouped by 14 industry kinds — each with accent/primary/secondary/canvas/ink + dark & footer colors). Pick one and pass its colors into create_project's brand block or update_project_branding. Read-only, no arguments.

list_campaigns

ChatGPT
List Brevo email campaigns for a client, optionally filtered by status.

list_clients

ChatGPT
List all managed client deployments with online status, Convex URL, agent domain, and timezone.

list_contacts

ChatGPT
List contacts for a client, optionally filtered by score bucket or free-text search.

list_document_history

ChatGPT
List the revision history of a Sanity document, NEWEST-FIRST: [{ rev, timestamp, author }]. Use to find a revision to inspect or roll back to. Returns status 'no_history_in_range' (not an error) when the document is older than the plan's history retention window. Read-only.

list_document_types

ChatGPT
Discover which Sanity document types exist in a client's dataset. Returns each _type with a count. Use this first to find non-page types (portfolio, testimonial, blog.post, etc.) before listing or fetching documents.

list_documents_by_type

ChatGPT
List documents of a specific Sanity _type with pagination. Returns _id, _type, _updatedAt, title, slug by default (override with fields). Use list_document_types first to discover what types exist.

list_drafts

ChatGPT
List outreach drafts for a client, optionally filtered by status.

list_email_history

ChatGPT
List inbound email replies recorded for an address (replies to campaigns/sequences, newest first). Returns { replyCount, replies: [{ id, from, subject, snippet, receivedAt (ISO) }] }.

list_media_assets

ChatGPT
List raw uploaded assets from a client's Sanity media library (images/files), newest first, with filename + asset ref. Use this to find uploaded photos to place via copy_asset or patch_card_image. Distinct from list_generated_assets (Creative Studio AI-generated assets only). Works for site-only clients.

list_pages

ChatGPT
List all pages in a client's SanityPress CMS with module metadata and counts. Read-only.

list_preview_sets

ChatGPT
Every design-preview SET ever generated for a planner project (newest first) — nothing is deleted when you regenerate, this is how you find the older ones. Each set: token, previewUrl, status, label, createdAt, createdVia, costUsd, kept/canonical/latest flags, and per-slot { index, model, tastePackIdentifier, selectedPaletteName, selectedReferenceName, status, costUsd, htmlAssetUrl }. Optional pageKey filter. Read-only. not_enabled if the operator API is unset.

list_sequences

ChatGPT
List Brevo email sequences (automations) for a client with step count and active contact count.

list_social_posts

ChatGPT
List this business's social posts (drafts, scheduled queue, published, failed) with full captions, times and postIds. Call this BEFORE writing new posts so you can see what was said recently and avoid repeating an angle, and to find postIds for schedule/reschedule/delete. Newest first.

list_taste_packs

ChatGPT
The Lab design-system vocabulary: every taste pack (design system) id + the selected pack's palette ARCHETYPES and visual REFERENCES with their fit tags. Use the names to steer generate_preview_set per-variant (variants[].paletteOverride / referenceOverride / tastePackIdentifier). Optional identifier arg selects a pack (default 'universal'). Read-only.

patch_card_image

ChatGPT
Set the image field on a specific card within a card-list module on a page. Convenience over patch_document — handles the image object construction (asset reference + alt). Pass the page _id, the card-list module _key, the card _key, the asset _id (e.g. 'image-abc123-1600x1000-webp'), and the alt text. Atomic single-card update; for batch card image updates use patch_document with multiple set patches.

patch_document

ChatGPT
Apply surgical patches to any Sanity document. Operations: set, unset, setIfMissing, insert (with numeric index or GROQ selector), splice (numeric-index array insert, recommended for stability). Always validates positional indices against current array length; uses ifRevisionID for optimistic concurrency. Returns 409-style error if the document was modified between fetch and write.

patch_page_metadata

ChatGPT
Update a page's SEO metadata — OG image, title, description, noIndex. Use after generate_asset to apply an OG image to a page.

patch_page_module

ChatGPT
Patch one or more fields on a specific module within a page's modules[] array, identified by module _key. Pass the page _id, the module _key, and a flat object of fields to set on that module — the tool builds the GROQ paths internally. Use this instead of patch_document when you only need to update a single module: clearer intent, less syntax noise. Atomic single transaction. Inherits ifRevisionID concurrency handling and 409 conflict surfacing from patch_document.

patch_site_settings

ChatGPT
Update the site singleton — title, blurb, copyright text. Plain text is automatically converted to Portable Text format.

pause_my_ad_campaign

ChatGPT
Pause one of the business's running campaigns now (account owner or a Manager only). It only stops spending, but confirm which campaign with the owner first. webfaCeMEdia is told. Switching it back on goes through webfaCeMEdia (ask_for_ads).

regenerate_preview_variant

ChatGPT
Regenerate ONE slot of an existing design-preview SET in place — the set token is kept (an already-sent link stays live and shows the new variant when it finishes), the other slots are untouched. Steer the slot with variant:{ tastePackIdentifier | paletteOverride | referenceOverride } (names from list_taste_packs) and/or switch its model. Call with dryRun:true first to see the plan + cost for that slot; pass rerun.variant + rerun.model back to run it. Costs one variant (4 images + one model call + 1 lab credit). Returns { ok, bundleId, setToken, index, previewUrl }. not_enabled if the operator API is unset.

remove_from_array

ChatGPT
Remove items from an array field by their _keys. Common uses: deleting stale modules from a page, removing outdated stats, dropping unused CTAs. Atomic — all removals commit in a single transaction.

reorder_page_modules

ChatGPT
Change the order of modules on a page. Pass the complete list of _keys in the desired order. Must include every module currently on the page.

replace_preview_image

ChatGPT
Swap ONE image in a Lab preview bundle, headlessly — no picker UI. Either provide newImageUrl, or generate:{prompt,purpose} to create the replacement first (purpose 'illustration' = swap a photo for a flat editorial illustration; also hero/card/product/…). The old image is matched by its exact URL in the bundle HTML (occurrenceIndex targets the Nth occurrence; omit = all). Persists a new bundle revision — the shared preview updates immediately. Generation burns the project owner's image quota. Body needs projectId (the bundle's parent project) for scoping. Returns { htmlAssetUrl, newImageUrl }.

reschedule_social_post

ChatGPT
Move a scheduled post to a new time on the calendar. Only works on status scheduled posts that have not started publishing. Ask the owner before moving a post they approved for a specific time.

reskin_bundle

ChatGPT
Re-skin already-generated Lab design(s) to the project's CURRENT branding — deterministically, at ~zero model cost. The flow: update_project_branding (set colors/fonts/logo once) → reskin_bundle. The server re-hues each bundle's original palette to the new brand (keeping every shade's lightness, so hovers/gradients stay coherent), applies font overrides, and — with includeLogo:true — points the header brand mark at the project's current logo (a logo <img> gets the new src; a text wordmark becomes the logo <img>; light/dark variant chosen by the bundle's canvas). Appends ONE new revision per bundle — layout, copy, other images untouched; NO AI regeneration, NO lab-generation quota. Omit bundleId to re-skin every completed bundle on the project; pass it to re-skin one. Returns { reskinned: [{ bundleId, version, htmlAssetUrl, replacedColors, logoReplaced, logoMode }], skipped }.

schedule_social_post

ChatGPT
Put a draft on the calendar (or publish it now). ONLY call this after the owner has approved this exact post and time in the conversation — then pass ownerConfirmed: true to record that; without it the call is refused. A future scheduledAt queues the post (status scheduled; the platform publishes it at that time and it appears on the dashboard calendar). A past or missing time publishes now: the post goes to status publishing (the platform retries transient errors with backoff) — check get_social_post a minute later for published (with publishedUrls) or failed (with error). Refused with missing_media if an Instagram/TikTok post has no image or video, and with no_connected_channels if the business has not linked its accounts yet (dashboard → Social → Channels).

search_content

ChatGPT
Full-text search across all page content for a client. Read-only.

send_client_preview

ChatGPT
Send a project's redesign preview SET to the client AFTER reviewing it (open previewUrl from get_project_status first). The email is FROM webfacemedia with the agency as reply-to, so client replies reach the agency. Requires a Solo/Agency plan. Approves the set as part of sending. To release a held set WITHOUT emailing, use approve_preview_set (or send:false here). Optional visibleBundleIds cherry-picks which of the set's completed variants the client sees. Returns { ok, status:'sent'|'approved', sentTo, visibleCount }. not_enabled if the operator API is unset.

update_contact

ChatGPT
Update status, notes, starred flag, or signal fields on an existing contact. Omitted fields are left unchanged.

update_project_branding

ChatGPT
Set brand colors / fonts / wordmark on a project (bulk typography edits across builds). branding accepts: primaryColor/secondaryColor/accentColor (+ darkCanvas/darkInk/footerBg/footerText/footerBgDark/footerTextDark) as #RRGGBB, fontHeading/fontBody as plain font names (e.g. 'Playfair Display'), wordmark as a short string. Explicit values are user-choice-wins — they persist through builds and Lab redesigns. Returns { ok, set }.

update_project_modules

ChatGPT
APPLY module edits that YOUR model generated — the platform validates shapes (keys, CTAs, module-specific rules), merges into moduleData, persists once, and meters the operation. Bulk-capable: pass up to 50 edits in one call; partial-failure tolerant (per-edit ok/error results). Get pageSlug/moduleKey/current content from get_project_content first. Each edit: { pageSlug, moduleKey, set } where set contains moduleData fields (heading, content, items[], ctas:[{label,style}] — flat CTAs are normalized to the canonical nested shape automatically). Refused with BUILD_IN_PROGRESS while a build is running on the project; 402 APPLY_EDITS_QUOTA_EXCEEDED past the plan's monthly apply quota. Returns { applied, results[] }.

update_social_draft

ChatGPT
Edit a draft or approved social post in place — captions, platforms, assets, postType, proposed time. Use this to apply the owner's edits or to attach the image an Instagram/TikTok post needs. Scheduled or published posts cannot be edited (reschedule or delete instead).

upload_media

ChatGPT
Upload a file you have — a photo, a graphic, a short video, or a PDF/PPT/DOC case study — to the business's media library and get back a permanent public URL plus a ready-made asset for create_social_draft / update_social_draft. Send the file as base64 (jpeg/png/webp/gif, mp4/mov, pdf/ppt/pptx/doc/docx). Up to 3 MB fits in one call. LARGER FILES (up to 25 MB, video 50 MB): split the bytes into ≤3 MB parts and call this tool once per part in order with partIndex (0-based), totalParts and — on part 0 — totalBytes (the whole file's size); part 0's response returns an uploadId to pass on every later part; the last part returns the asset. If you can make HTTP requests yourself, begin_upload_url + finish_upload is faster. A PDF or other document publishes only as a native LinkedIn document (carousel) post: the draft must be LinkedIn-only with that one asset and nothing else, and the first line of the LinkedIn caption becomes the document title. Check list_media_assets first — if the file is already in the library, reuse its url instead of uploading again.

upload_sanity_asset

ChatGPT
Put a file you already HAVE into the client's Sanity dataset and get back the asset ref that patch_document / patch_page_module / patch_card_image take — the ingest half of the Creative Studio (generate_asset MAKES images; this one uploads an existing logo, real headshot, brochure PDF, etc.). Pass exactly one source: fileBase64 (bytes inline, ≤ 3 MB decoded) or sourceUrl (an https URL fetched server-side, ≤ 25 MB — a list_media_assets url, a cdn.sanity.io url, a page on the client's own site). Images (jpeg/png/webp/gif/svg/avif) become image assets; pdf/office/csv/video/audio/fonts become file assets. Returns assetRef, the CDN url, and a ready field object to set on any image/file field (add alt yourself). Sanity dedupes by content hash, so re-uploading the same bytes returns the same ref. Not for social posts — use upload_media for the media library.

upsert_document

ChatGPT
CREATE or fully REPLACE a Sanity document. REPLACE is destructive: any field on the stored document that is absent from your payload is permanently deleted. For editing specific fields on an existing document, DO NOT use this — use patch_document (or the purpose-built patch_page_module / append_to_array / remove_from_array), which change only the fields you name and cannot drop anything else. Use upsert_document only to create a brand-new document or to deliberately overwrite an entire document. Always fetch the complete current document with get_document first if replacing. Requires confirmDestructive: true. If the payload would drop existing fields, the call is refused unless confirmReplace: true is also set.

Capabilities

Writes

Example Prompts

Click any prompt to copy it.

App Stats

80

Tools

3

Prompts

ChatGPT

Platforms

Works with

ChatGPT

Data refreshed daily