External approvals — action checklist
Action-oriented checklist for the Meta + LinkedIn + WhatsApp approvals that gate live publishing in the social and dm-inbox lanes. Engineering reference docs in this directory describe API surfaces; this file describes the human dashboard work that has to land before that code can call those APIs.
Status as of 2026-05-05: none started. All four tracks below need to be kicked off. Total elapsed time from "submit everything" to "everything approved" is typically ~2-3 weeks.
Update the checkboxes as you progress so a future session can see where things stand.
Why this file exists
Q3 social publishing (PR #28/#29/#30, all merged) and DM-inbox slice 3 (Messenger webhook, not started) are gated on Meta + LinkedIn approvals. WhatsApp Business replaces the deferred Slack SLA-alert path per #39. The code is or will be ready before the access tokens are — the bottleneck is approval cycles, not implementation.
Each track lists the exact dashboard steps, what to write in the use-case forms, what tokens to capture, and what env vars they map to in this repo's .env.example.
Order of operations recommendation
- Today: Start Business Verification (prereq below). Apply for LinkedIn Marketing Developer Platform (Track 3) — independent of Meta, parallel.
- Day 1-7 while waiting on Business Verification: Write privacy + terms pages on the public
michiu.nlsite if missing (Meta requires public URLs — Cloudflare-Access-gated docs will fail review). Record screencasts for Tracks 1 + 2 against mock-mode. - Once Business Verification clears: Submit all five Meta permissions (Track 1 + 2). Start WhatsApp number provisioning (Track 4).
- Day 14-21: Approvals roll in. Capture tokens. Drop into
.env.local(or Vercel env post-migration). Smoke-test publishing + DM receive.
Prereqs (block all Meta tracks; do these FIRST)
Meta Business Manager + Business Verification
- Open https://business.facebook.com — confirm Quarb / Michiu Business Manager exists. If not, create one.
- Business Info → Submit verification documents. Meta needs proof the business is real:
- Business registration / KvK extract (Dutch chamber of commerce — Michiu is registered in NL)
- Utility bill OR phone bill in the business name (matching address)
- Business website URL:
michiu.nl
- Wait for Business Verification to complete. This is the long pole — 3-7 days typical. App reviews can be submitted in parallel but won't be granted until this clears.
- Confirm a public URL hosts a privacy policy + terms of service.
marketing.qhosty.comis Cloudflare-Access-gated → will fail Meta review. Ifmichiu.nldoesn't have these pages, add/privacyand/termsto the public site repo (michiu-website).
App in Meta for Developers
- At https://developers.facebook.com/apps/, create app "Michiu Marketing" (or use existing if present).
- App type: Business
- Link the app to the Michiu Business Manager (mandatory for the permissions below)
- Add products: Facebook Login, Instagram Graph API, Messenger, WhatsApp
Track 1 — Meta app review for SOCIAL lane (publishing)
Permissions to request, one at a time, in the app dashboard's App Review → Permissions and Features:
-
pages_show_list— list pages the connecting user manages -
pages_read_engagement— read engagement signals -
pages_manage_posts— publish to FB Page -
instagram_basic— read IG account info -
instagram_content_publish— publish to IG (feed / reel / story)
For each permission, the form asks for:
- Use case description — paste roughly:
"Michiu uses this app to schedule and publish branded content to its own Facebook Page and Instagram Business account from an internal admin console. Posts are drafted by staff, AI-generated captions are reviewed and approved by a human, then queued for publishing via this API."
- Screencast — Meta's #1 rejection reason. Record the
/admin/postsflow end-to-end: paste content → 3 variants generated → approve one → schedule → see "scheduled" in calendar → simulate publish (runpnpm cron:tickfor the demo). - Test instructions — give the reviewer a working test account on whatever URL the admin console runs at by submission time. Mock-mode is acceptable for the demo since reviewers care about the UX, not whether bytes flew.
- Privacy policy URL + Terms URL — public, no auth gate.
After approval, capture and drop into .env.local:
- Page access token — generate a long-lived (~60 days) token via Graph Explorer, OR generate a System-User token under Business Manager → System Users (no expiry). Prefer system-user. Maps to
META_PAGE_ACCESS_TOKEN. -
META_FACEBOOK_PAGE_ID— Page → About → Page ID -
META_INSTAGRAM_BUSINESS_ID— IG must be linked to the FB Page; ID is in Page Settings → Linked Accounts -
META_GRAPH_API_VERSION— already defaults tov22.0in the code. Bump if Meta deprecates.
Timing: ~1-2 weeks after submission, assuming Business Verification has cleared.
Code state: publishers in src/lib/posts/publishers/meta/ (PR #29). All four channels (instagram-feed, instagram-reel, instagram-story, facebook) ready. Will throw MetaConfigError until env vars exist.
Track 2 — Meta app review for DM-INBOX lane (slice 3 webhook)
Same Meta Business Manager + same app. Different permission set, separate App Review submissions.
-
pages_messaging— receive + send FB Messenger messages on behalf of the Page -
instagram_manage_messages— receive + send IG DMs
For each permission, the form asks for:
- Use case description — paste roughly:
"Michiu's admin console receives inbound DMs from guests via Messenger and Instagram, classifies intent (booking inquiry / compliment / question / complaint / etc.), and proposes brand-voice replies that staff approve before sending. Sending uses the standard 24-hour customer-service window."
- Screencast — record the
/admin/dmsflow once slice 2 (PR #41) is merged: paste an inbound DM → enrichment + 3 variants render → approve one → "Mark replied manually" or send. Mock-mode is fine for the demo. - Test instructions + privacy/terms — same as Track 1.
Webhook setup (slice 3 work — do AFTER approval):
- In the app dashboard → Messenger product → Webhooks, register
https://<your-vercel-domain>/api/webhooks/messengeronce Vercel hosts the admin app. - Generate
META_VERIFY_TOKEN(any random string of your choosing) for the GET handshake. - Copy
META_APP_SECRETfrom app dashboard → Settings → Basic — used forX-Hub-Signature-256HMAC verification on every inbound webhook. - Subscribe to webhook fields:
messages,messaging_postbacks(FB);messages(IG). - Under Messenger → Settings, "Add or Remove Pages" → add the Michiu FB Page. Repeat for IG under the Instagram product.
After approval, capture:
- Same page access token as Track 1 (scopes overlap — likely a single system-user token works for both lanes).
Timing: ~1-2 weeks after submission. Cannot live-test until Vercel migration also lands (webhook needs a public HTTPS endpoint).
Code state: none yet — slice 3 work. Lane operating contract: .claude/lanes/dm-inbox.CLAUDE.md.
Track 3 — LinkedIn Marketing Developer Platform
Independent of Meta — different ecosystem, same approval pattern.
- At https://developer.linkedin.com → My Apps, create app "Michiu Marketing" linked to the Michiu LinkedIn Company Page.
- The Company Page must be verified.
- The submitter must be a Page admin.
- Apply for Marketing Developer Platform: https://www.linkedin.com/developers/products/marketing-developer-platform
- Use case: "Posting branded organization content to the Michiu LinkedIn Company Page from an internal admin tool with approval-gated drafts."
- Brief description of the company + plan to use the API.
- Some reviewers ask for a screencast — have one ready.
- Required scope:
w_organization_social(post on behalf of org). Optional but useful:r_organization_social(read posts back),rw_organization_admin(manage page). - Add an OAuth 2.0 redirect URL in app settings — must match where the auth dance runs (e.g.,
http://localhost:3000/api/linkedin/callbackfor local dev).
After approval, capture and drop into .env.local:
- Run the OAuth 2.0 3-legged auth flow once to get an access token (~60-day TTL; refresh tokens extend it). The dev portal has a "Generate access token" button that handles this for testing — fine for production single-tenant use.
-
LINKEDIN_ACCESS_TOKEN— the bearer token. -
LINKEDIN_ORGANIZATION_ID— find by visitinghttps://www.linkedin.com/company/<slug>/admin/and copying the numeric ID from the URL. Code accepts either bare numeric or fullurn:li:organization:{id}. -
LINKEDIN_API_VERSION— already defaults to202410in the code; bump if LinkedIn rolls forward.
Timing: ~1-2 weeks. Independent of Meta.
Code state: publisher in src/lib/posts/publishers/linkedin.ts (PR #30). Single + multi-image flows ready; video deferred. Will throw a config error until env vars exist.
Track 4 — WhatsApp Business API (replaces Slack for SLA alerts per #39)
Same Meta Business Manager + same app, separate WhatsApp product flow.
- In the Meta app dashboard, add the WhatsApp product if not already added.
- Provision a phone number — three options:
- Buy a new number through Meta (cleanest for a fresh business line).
- Port an existing landline / mobile — must NOT have been used on consumer WhatsApp in the last ~30 days, or it'll be rejected.
- Use Meta's free test number for development first.
- Display name approval — submit "Michiu" or "Restaurant Michiu". Approval is 1-3 days. Must comply with WhatsApp Business display name guidelines — no generic words, no profanity, must match registered business name.
- Message templates — for SLA alerts to staff, need a utility template, e.g.:
- Template name:
urgent_review_alert - Category: Utility
- Body: "Urgent review at {{1}}: {{2}}-star from {{3}}. {{4}}" with a button to open the admin console.
- Submit for approval — 1-3 days per template.
- Template name:
After approval, capture:
- WABA ID (WhatsApp Business Account ID) — Meta Business Manager → WhatsApp Manager.
- Phone Number ID — same place, distinct from WABA ID.
- System User access token — Meta Business Manager → System Users → create a system user → assign WhatsApp permissions → generate token (no expiry). Recommended over user tokens.
- When the adapter PR lands, add
WHATSAPP_PHONE_NUMBER_ID,WHATSAPP_ACCESS_TOKEN,WHATSAPP_RECIPIENT_PHONE(staff WhatsApp number) to.env.example.
Timing: Phone + display name 1-3 days; templates 1-3 days each. Total ~1 week if no rejections.
Code state: none yet. Per #39, the WhatsApp adapter waits for verified API access before being written (lesson from #34 — don't pre-write against guessed API shapes). PR #7's Slack code stays merged as a no-op.
What I (Claude) can do once tokens exist
When the env vars are populated:
- Smoke-test the social lane against a single test post on each channel (
pnpm cron:tickagainst a realposts.scheduled_for = now). - Write the WhatsApp notification adapter — likely lives at
src/lib/notifications/whatsapp.tsparallel to the existing Slack code insrc/lib/reviews/notifications.ts. - Bump
dm-enrich-v1.0→v2.0once we have real DMs to calibrate the prompt against (build the regression suite alongside per the dm-inbox lane's known-gaps list).
What's NOT in this checklist
- Vercel migration — separate workstream. Deferred per user 2026-05-05 ("transfer to Versel when everything is finished"). Track 2's webhook receiver and the cron worker for Track 1 both block on this for production. Local-only dev unblocks during the wait.
- Anthropic credit top-up — not an "approval", just a billing action. Caption generator + enrich-v2 vision + DM enrichment all fall back to mock without it. https://console.anthropic.com/settings/billing
- Zenchef partner-API access — guest-intel lane, separate ask via api-tech-help@zenchef.com. Tracked in
.claude/lanes/handoffs/guest-intel.HANDOFF.md. - Google Ads API dev token — ads lane, Q1-Q2 2027. Tracked in
.claude/lanes/handoffs/ads.HANDOFF.md.