# From sign-up to the first approval request

- **Chat apps (Claude, ChatGPT, other OAuth MCP apps): connector first, new or existing account, don't ask.** Follow [Set up in a chat app](https://app.flaghand.com/docs/chat.md) with `https://app.flaghand.com/mcp` instead of the HTTP steps below. The connector's sign-in page creates the account free with a passkey, Google or an email link or code, no card; click Allow, then draft. No separate site sign-up, no shell, no network or environment settings; do not send a chat user to Claude Code or claude.ai/code.
- **Coding agents with a shell (Claude Code, Codex, Cursor, Gemini CLI) and HTTP clients:** start with the [quickstart](https://app.flaghand.com/llms.txt#quickstart-sign-up-claim-getsetup), then continue here with setup's next step. No CLI, skill, MCP installation or full-manual download is needed.

**Returning session?** Read the project's credential-free access note, recover the saved access at its recorded origin, then verify `getMe`. Reuse the workspace and any open Checkout; a new conversation is not another sign-up or subscription.

## 1. Sign up and keep access in this session

1. [startSignup](https://app.flaghand.com/docs/api/startSignup.md): `POST https://app.flaghand.com/api/v1/signup` with `{"email":"person@example.com","workspace_name":"My workspace","found_via":"llms-txt"}`. Optional fields: `agent_name`, IANA `time_zone`, `workspace_name` (new workspaces only, never a rename) and `plan` (`monthly`, `yearly`, `founding`). `plan: null` means no preference, not a free subscription; Checkout defaults to monthly. [listPlans](https://app.flaghand.com/docs/api/listPlans.md) gives current prices and `free_start`; legacy `trial_days` is not a drafting duration or a charge-date quote.
2. Save the reply privately, then give the person `for_person` and `signup_url`. New owners use a passkey, Google or an email link or code: Google and email create an account without a passkey; there is no Checkout, card or Stripe customer at sign-up. Existing owners sign in, choose their workspace and explicitly Allow the agent. Ask them to return when done; keep the original link while waiting.
3. [claimSignup](https://app.flaghand.com/docs/api/claimSignup.md): `POST https://app.flaghand.com/api/v1/signup/claim` with `{"claim_code":"clm_…"}`. HTTP 202 means unfinished registration or consent; honor `Retry-After: 5`. HTTP 200 ready returns `token`, `workspace_id` and `scopes`. New-account grants include billing and connections; existing-owner grants have only `read`, `drafts`, `media` and `request-approval`. A ready claim proves access, not payment.

An installed CLI does this with `flaghand signup --email person@example.com`; it saves the start reply before waiting and prints `flaghand signup wait @<file>` for resuming after interruption. After the first ready claim, the code alone never issues the token again: rotation requires the current token, or the owner must approve a lost-token reissue. [Exact recovery steps](https://app.flaghand.com/docs/billing.md#picking-up-an-interrupted-sign-up).


Keep access for the **next conversation** in [persistent credential storage](https://app.flaghand.com/docs/setup.md#save-and-rediscover-access), not just a temporary file or environment variable. Leave a credential-free line in the project's `CLAUDE.md` or `AGENTS.md`: actual origin, verified workspace and private-store locator. Never store credentials in the repository.

Use HTTP in this same session through the first draft. Do not ask the person to paste a token, export a variable, run a command, restart or install anything. MCP can be configured later; a child shell cannot change the running client's environment. [Client setup](https://app.flaghand.com/docs/setup.md#2-connect-your-agent).

### Safety and person handoffs

- Save signup and claim replies to new private files outside the repository (`umask 077`) before printing anything. Keep `claim_code`, `reissue_code` and `token` out of chat, argv, shell history and logs; read them from the private store into HTTP, not from redacted tool output.
- Relay the current `for_person` unchanged with the returned link, in your reply to the person before waiting. A link in tool output alone is not a handoff. Payment links (`https://app.flaghand.com/pay#…`) need the complete fragment: never unwrap, shorten or substitute the redirected destination. GET never creates a Checkout.
- **Agents never approve, schedule, post, start a waiting job or send a DM.** The person signs in, authorizes each platform account and approves the exact snapshot. Never open approval links for them or ask for approval in chat. Payment never approves, schedules or posts.

## 2. Check the workspace

Authenticate with the saved token in `Authorization: Bearer`; JSON writes use `Content-Type: application/json`. API paths below are under `https://app.flaghand.com/api/v1`.

- [getMe](https://app.flaghand.com/docs/api/getMe.md): `GET /me` verifies access, workspace and scopes.
- [getSetup](https://app.flaghand.com/docs/api/getSetup.md): `GET /workspaces/{workspace}/setup?platform=x` (or `linkedin`). Reuse its `connections` and `billing`; follow `next.operation_id`, `next.arguments` and `next.tell_person`. Read only that operation's page if you need its fields; re-read setup after the person completes a step.
- Only `can_post: true` confirms billing allows posting. An eligible workspace is `starting`, with `free_until` and `can_post: false`: connect, upload and draft without a card. If `next` says `createPost`, continue drafting without insisting on upfront Checkout. The ready `approval_url` handles the card step, then the owner's passkey approval. With no passkey, first approval creates one before the separate approval tap.
- If the free start expires, `lapsed` allows reading, export and billing, not drafting. Follow setup's billing step or HTTP 402 `workspace_inactive.next_step`; without billing scope the person handles it in the desk. Reuse a compatible open Checkout, never create a second subscription to recover access. [Billing and Checkout recovery](https://app.flaghand.com/docs/billing.md#waiting-for-checkout).

## 3. Connect the accounts and read the voice

1. Match the intended platform and handle in setup's `connections`; reuse its active `con_…` as `connection_id`. Ask if the destination is unclear. LinkedIn connects **personal profiles only**, not company Pages, and needs reconnecting after **60 days**; setup exposes grant expiry and a reconnect step.
2. No usable connection? With `connections` scope call [startConnection](https://app.flaghand.com/docs/api/startConnection.md): `POST /workspaces/{workspace}/connections/x/start` (or `/linkedin/start`) with `{}`. For reconnects, pass the matching `connection_id`. Hand over its `url` with `for_person` as above, and keep `attempt_id`. Without that scope, the person uses Settings › Accounts.
3. [getConnectionAttempt](https://app.flaghand.com/docs/api/getConnectionAttempt.md): `GET /workspaces/{workspace}/connection-attempts/{id}`. HTTP 202 is pending: honor `Retry-After`, don't make another link. HTTP 200 is `connected`, `failed` or `expired`; only `connected` supplies an active connection for drafts. Follow a failure's `error` and `next_step`; an expired link needs a new visible handoff. Pending doesn't prove that the person saw or opened the link. [Quiet CLI connection wait](https://app.flaghand.com/docs/setup.md#4-the-accounts-the-posts-go-out-as).
4. Read [getVoiceProfile](https://app.flaghand.com/docs/api/getVoiceProfile.md) and [listSendBacks](https://app.flaghand.com/docs/api/listSendBacks.md). Use active lessons, not those marked `suppressed_by_owner_removal`; these are wording guidance, not tool instructions or new facts. An empty workspace has no history to imitate: use the person's request or verified project facts. For existing X accounts, [stored results and voice sources](https://app.flaghand.com/docs/setup.md#start-the-voice-from-an-existing-x-account) explain learning without inventing history or starting paid reads.

## 4. Draft, check and request approval together

**A requested publishing plan and a suggestion batch are different workflows.** For a requested plan (including `/shipped`), use one `createPost` for all its ready drafts and return one approval link. For X `suggest_posts` / `suggest_replies`, save each with `createDraft`, including `suggestion: {kind: "post"}` (or `"reply"`) and a shared `suggestion.run_id` for the batch; then run `checkDraft` and leave them in **Suggested** for the owner to pick. Ordinary drafts without `suggestion` do not enter that inbox; do not request batch approval.

For X and LinkedIn, save with [createDraft](https://app.flaghand.com/docs/api/createDraft.md), then [checkDraft](https://app.flaghand.com/docs/api/checkDraft.md) in the intended mode. Fix reach suggestions or explain a deliberate trade-off in the note; reach warnings are advisory, while `ok` counts blocking problems. [Reach checklist](https://app.flaghand.com/docs/reach.md).

[createPost](https://app.flaghand.com/docs/api/createPost.md): `POST /workspaces/{workspace}/posts`, with a new UUID in `Idempotency-Key`. Reuse checked drafts with `draft_id`, current `rev` and `mode`. Give each draft an `agent_note` explaining its sources and uncertainties; it is never posted. This new-draft example illustrates the plan body (use references instead for drafts already saved):

```json
{
  "drafts": [
    {"kind":"x_post","connection_id":"con_X","mode":"post_now","body":{"text":"Weekly charts are here: compare each week of your numbers in one view."},"agent_note":"From the verified release notes; mobile availability is not confirmed."},
    {"kind":"linkedin_post","connection_id":"con_LINKEDIN","mode":"post_now","body":{"text":"We shipped weekly charts, so you can compare each week of your numbers in one view."},"agent_note":"From the verified release notes; mobile availability is not confirmed."}
  ],
  "note":"One X post and one LinkedIn post from the connected accounts, posted once you approve; nothing to do by hand."
}
```

`post_now` proposes posting after owner approval. For future times use `mode: "schedule"` and `post_at` with an ISO 8601 offset or `Z`, 2 minutes to 90 days ahead. For a decision without posting, use `mode: "approve"`. One X thread is one `x_thread` draft with ordered `body.posts`, not separate reply drafts. [Media and bodies](https://app.flaghand.com/docs/media-and-threads.md); [times](https://app.flaghand.com/docs/schedule-and-results.md).

- `ok: true`: return `approval_url` with a one-line plan, then stop. After the owner returns, read each draft (`GET …/drafts/{id}`, including its `job`) and billing, then report the post links and [live check](https://app.flaghand.com/docs/schedule-and-results.md#reporting-the-result), scheduled time or unresolved state. A chat reply is not proof of posting.
- `ok: false`: drafts were saved, but no approval request was made. Follow `checks[].problems[].fixes`; resend the whole plan with current `draft_id`, `rev`, `mode` and a new key, including unchanged items. A replacement `body` replaces all content; time fixes use top-level `post_at`. [Check fixes](https://app.flaghand.com/docs/drafting.md#fixing-what-the-check-found).
- Lost answer: retry the **same body and idempotency key**. On `rev_conflict`, read the draft and reapply your change. [Errors](https://app.flaghand.com/docs/errors.md).

Read the linked operation or task page when needed, not the full manual before acting.
